LCOV - code coverage report
Current view: top level - src/46_ghc_omp - m_ompgpu_fourwf.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 15 0
Test Date: 2026-11-06 01:31:13 Functions: 0.0 % 5 0
Branches: 0.0 % 2 0

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_ompgpu_fourwf
       2                 :             : !! NAME
       3                 :             : !!  m_ompgpu_fourwf
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  Fake module to dupe the build system and allow it to include cuda files
       7                 :             : !!   in the chain of dependencies.
       8                 :             : !!
       9                 :             : !! COPYRIGHT
      10                 :             : !!  Copyright (C) 2000-2026 ABINIT group (MT)
      11                 :             : !!  This file is distributed under the terms of the
      12                 :             : !!  GNU General Public License, see ~abinit/COPYING
      13                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      14                 :             : !!
      15                 :             : !! SOURCE
      16                 :             : 
      17                 :             : #if defined HAVE_CONFIG_H
      18                 :             : #include "config.h"
      19                 :             : #endif
      20                 :             : 
      21                 :             : #include "abi_common.h"
      22                 :             : 
      23                 :             : module m_ompgpu_fourwf
      24                 :             : 
      25                 :             :  use defs_basis
      26                 :             :  use m_abicore
      27                 :             :  use m_gputk
      28                 :             :  use m_abi_linalg
      29                 :             :  use m_errors
      30                 :             :  use m_xomp
      31                 :             :  use iso_c_binding
      32                 :             : 
      33                 :             : #ifdef HAVE_GPU
      34                 :             :  use m_gpu_toolbox
      35                 :             : #endif
      36                 :             : 
      37                 :             :  implicit none
      38                 :             : 
      39                 :             :  private
      40                 :             : 
      41                 :             : #ifdef HAVE_OPENMP_OFFLOAD
      42                 :             : 
      43                 :             : ! STATIC vars to avoid too much cuda overhead
      44                 :             : integer :: fourdp_initialized=0
      45                 :             : integer :: fourwf_initialized=0
      46                 :             : 
      47                 :             : #define FOURDP_ID 1
      48                 :             : #define FOURWF_ID 0
      49                 :             : 
      50                 :             : ! FFT plans
      51                 :             : integer :: fft_size_fourdp=-1
      52                 :             : integer :: ndat_fourdp=-1
      53                 :             : integer :: fft_size_fourwf=-1
      54                 :             : integer :: ndat_fourwf=-1
      55                 :             : 
      56                 :             : #endif
      57                 :             : 
      58                 :             :  public :: ompgpu_fourdp
      59                 :             :  !public :: alloc_ompgpu_fourdp
      60                 :             :  !public :: free_ompgpu_fourdp
      61                 :             :  public :: ompgpu_fourwf
      62                 :             :  public :: alloc_ompgpu_fourwf
      63                 :             :  public :: free_ompgpu_fourwf
      64                 :             : 
      65                 :             :  ! This routine is here to assess memory requirements
      66                 :             :  public :: ompgpu_fourwf_work_mem
      67                 :             : contains
      68                 :             : 
      69         [ #  # ]:           0 : function ompgpu_fourwf_work_mem(ngfft, ndat) result(req_mem)
      70                 :             : 
      71                 :             :  integer, intent(in) :: ngfft(:), ndat
      72                 :             :  integer(kind=c_size_t) :: req_mem
      73                 :             : 
      74                 :           0 :  req_mem = int(2, c_size_t) * dp * ngfft(1) * ngfft(2) * ngfft(3) * ndat
      75                 :             : 
      76                 :           0 : end function ompgpu_fourwf_work_mem
      77                 :             : 
      78                 :             : !Tested usecases :
      79                 :             : ! - Nvidia GPUs : FC_NVHPC + CUDA
      80                 :             : ! - AMD GPUs    : FC_LLVM + HIP
      81                 :             : ! An eventual Intel implementation would use the OneAPI LLVM compiler.
      82                 :             : ! Homemade CUDA/HIP interfaces would allow the use of GCC.
      83                 :             : ! But it is likely that OpenMP performance won't be optimal outside GPU vendors compilers.
      84                 :             : #ifdef HAVE_OPENMP_OFFLOAD
      85                 :             : 
      86                 :             : subroutine ompgpu_fourdp(cplex,ngfft,ldx,ldy,ldz,ndat,isign,fofg,fofr)
      87                 :             : 
      88                 :             : !Arguments ------------------------------------
      89                 :             : !scalars
      90                 :             :  integer,intent(in) :: cplex,ngfft(18),ldx,ldy,ldz,ndat,isign
      91                 :             : !arrays
      92                 :             :  real(dp),target,intent(inout) :: fofg(2*ldx*ldy*ldz*ndat)
      93                 :             :  real(dp),target,intent(inout) :: fofr(cplex*ldx*ldy*ldz*ndat)
      94                 :             : 
      95                 :             : !Local variables-------------------------------
      96                 :             : !scalars
      97                 :             :  integer      :: n1,n2,n3,nfft_tot
      98                 :             :  complex(dp) :: norm
      99                 :             :  logical      :: transfer_fofr, transfer_fofg
     100                 :             :  character(len=500) :: msg
     101                 :             : ! *************************************************************************
     102                 :             : 
     103                 :             :  n1=ngfft(1);
     104                 :             :  n2=ngfft(2);
     105                 :             :  n3=ngfft(3);
     106                 :             :  nfft_tot=n1*n2*n3;
     107                 :             :  norm=dcmplx(one/(n1*n2*n3), 0.0_dp)
     108                 :             : 
     109                 :             :  !*********** CHECK some compatibilities **************
     110                 :             :  if( (n1/=ldx) .or. (n2/=ldy) .or. (n3/=ldz)) then
     111                 :             :    write(msg,"(a,a,i5,i5,i5,a,i5,i5,i5,a)") "FFT SIZE ERROR: \n when gpu mode is on the fft grid must not be augmented",&
     112                 :             :     "(n1,n2,n3) = (", n1,n2,n3,") whereas (ldx,ldy,ldz) = (", ldx,ldy,ldz, ")"
     113                 :             :    ABI_ERROR(msg)
     114                 :             :  end if
     115                 :             : 
     116                 :             :  ! ***********  GPU ALLOCATIONS  ***********************
     117                 :             : 
     118                 :             :  if (fourdp_initialized == 0) then
     119                 :             :    call alloc_ompgpu_fourdp(ngfft,ndat)
     120                 :             :  endif !end of initialisation
     121                 :             : 
     122                 :             :  ! If fft size has changed, we realloc our buffers
     123                 :             :  if((nfft_tot/=fft_size_fourdp) .or. (ndat/=ndat_fourdp)) then
     124                 :             :    call free_ompgpu_fourdp()
     125                 :             :    call alloc_ompgpu_fourdp(ngfft,ndat)
     126                 :             :  end if !end if "fft size changed"
     127                 :             : 
     128                 :             :  transfer_fofg=   .not. xomp_target_is_present(c_loc(fofg))
     129                 :             :  transfer_fofr=   .not. xomp_target_is_present(c_loc(fofr))
     130                 :             : 
     131                 :             :  !$OMP TARGET ENTER DATA MAP(alloc:fofg)    IF(transfer_fofg)
     132                 :             :  !$OMP TARGET ENTER DATA MAP(alloc:fofr)    IF(transfer_fofr)
     133                 :             :  !$OMP TARGET UPDATE TO(fofg) IF(transfer_fofg .and. isign==FFT_INVERSE)
     134                 :             :  !$OMP TARGET UPDATE TO(fofr) IF(transfer_fofr .and. isign==FFT_FORWARD)
     135                 :             : 
     136                 :             :  select case (cplex)
     137                 :             :  case (2)
     138                 :             :    ! Complex to Complex.
     139                 :             :    select case (isign)
     140                 :             :    case (FFT_INVERSE) ! +1
     141                 :             :      !$OMP TARGET DATA USE_DEVICE_ADDR(fofg,fofr)
     142                 :             :      call gpu_fft_exec_z2z(FOURDP_ID, c_loc(fofg), c_loc(fofr), FFT_INVERSE)
     143                 :             :      !$OMP END TARGET DATA
     144                 :             :      call gpu_fft_stream_synchronize(FOURDP_ID)
     145                 :             :    case (FFT_FORWARD) ! -1
     146                 :             :      !$OMP TARGET DATA USE_DEVICE_ADDR(fofg,fofr)
     147                 :             :      call gpu_fft_exec_z2z(FOURDP_ID, c_loc(fofr), c_loc(fofg), FFT_FORWARD)
     148                 :             :      !$OMP END TARGET DATA
     149                 :             :      call gpu_fft_stream_synchronize(FOURDP_ID)
     150                 :             :      ! Normalize here
     151                 :             :      call abi_xscal(ldx*ldy*ldz*ndat,norm,fofg,1,x_cplx=2,gpu_option=ABI_GPU_OPENMP)
     152                 :             :    case default
     153                 :             :      ABI_BUG("Wrong isign")
     154                 :             :    end select
     155                 :             :  case (1)
     156                 :             :    ! Real case.
     157                 :             :    ABI_BUG("Real case for OpenMP GPU fourdp not handled yet !")
     158                 :             :    !select case (isign)
     159                 :             :    !case (ABI_FFTW_BACKWARD) ! +1
     160                 :             :    !  ! +1; G --> R
     161                 :             :    !  call fftw3_c2r_op(nx,ny,nz,ldx,ldy,ldz,ndat,fofg,fofr)
     162                 :             :    !case (ABI_FFTW_FORWARD)  ! -1
     163                 :             :    !  ! -1; R --> G
     164                 :             :    !  call fftw3_r2c_op(nx,ny,nz,ldx,ldy,ldz,ndat,fofr,fofg)
     165                 :             :    !case default
     166                 :             :    !  ABI_BUG("Wrong isign")
     167                 :             :    !end select
     168                 :             :  end select
     169                 :             : 
     170                 :             :  !$OMP TARGET UPDATE FROM(fofg) IF(transfer_fofg .and. isign==FFT_FORWARD)
     171                 :             :  !$OMP TARGET UPDATE FROM(fofr) IF(transfer_fofr .and. isign==FFT_INVERSE)
     172                 :             :  !$OMP TARGET EXIT DATA MAP(delete:fofg)    IF(transfer_fofg)
     173                 :             :  !$OMP TARGET EXIT DATA MAP(delete:fofr)    IF(transfer_fofr)
     174                 :             : 
     175                 :             : end subroutine ompgpu_fourdp
     176                 :             : 
     177                 :             : subroutine ompgpu_fourwf(cplex,denpot,fofgin,fofgout,fofr,gboundin,gboundout,istwf_k,&
     178                 :             : &  kg_kin,kg_kout,mgfft,me_g0,ndat,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i,&
     179                 :             : &  use_ndo,fofginb)
     180                 :             : 
     181                 :             : !Arguments ------------------------------------
     182                 :             : !scalars
     183                 :             :  integer,intent(in) :: cplex,istwf_k,ldx,ldy,ldz,me_g0,ndat,npwin,npwout,option,mgfft
     184                 :             :  real(dp),intent(in) :: weight_i(ndat),weight_r(ndat)
     185                 :             :  integer,intent(in),optional :: use_ndo
     186                 :             : !arrays
     187                 :             :  integer,intent(in) :: gboundin(2*mgfft+8,2),gboundout(2*mgfft+8,2)
     188                 :             :  integer,intent(in) :: kg_kin(3,npwin),kg_kout(3,npwout),ngfft(18)
     189                 :             :  real(dp),target,intent(inout) :: denpot(cplex*ldx,ldy,ldz)
     190                 :             :  real(dp),target,intent(in)    :: fofgin(2,npwin*ndat)
     191                 :             :  real(dp),target,intent(inout) :: fofr(2,ldx,ldy,ldz*ndat)
     192                 :             :  real(dp),target,intent(out)   :: fofgout(2,npwout*ndat)
     193                 :             :  real(dp),target,intent(inout),optional :: fofginb(2,npwin*ndat)
     194                 :             : 
     195                 :             : !Local variables-------------------------------
     196                 :             : !scalars
     197                 :             :  character(len=500) :: msg
     198                 :             :  real(dp),allocatable,target :: fofrb(:,:,:,:)
     199                 :             :  logical :: l_use_ndo
     200                 :             : 
     201                 :             :  real(dp) :: xnorm,one,tmp
     202                 :             : 
     203                 :             :  integer :: n1,n2,n3,nfft_tot,npwmin,izd
     204                 :             :  integer :: cfft_size
     205                 :             :  integer :: shift_inv1,shift_inv2,shift_inv3
     206                 :             :  integer :: i1,i2,i3,ipw,idat;
     207                 :             :  integer :: i1inv,i2inv,i3inv
     208                 :             :  logical :: transfer_fofgin, transfer_fofginb, transfer_fofgout, transfer_denpot, transfer_fofr
     209                 :             :  integer(C_SIZE_T) :: byte_count
     210                 :             :  real(dp), contiguous, pointer :: work_gpu(:,:,:,:)
     211                 :             : 
     212                 :             :  npwmin=1; if(me_g0==1 .and. istwf_k==2) npwmin=2
     213                 :             :  l_use_ndo=.false.; if(present(use_ndo)) l_use_ndo=use_ndo==1
     214                 :             : 
     215                 :             :  n1=ngfft(1);
     216                 :             :  n2=ngfft(2);
     217                 :             :  n3=ngfft(3);
     218                 :             :  nfft_tot=n1*n2*n3;
     219                 :             : 
     220                 :             :  !*********** CHECK some compatibilities **************
     221                 :             :  if( (n1/=ldx) .or. (n2/=ldy) .or. (n3/=ldz)) then
     222                 :             :    write(msg,"(a,a,i5,i5,i5,a,i5,i5,i5,a)") "FFT SIZE ERROR: \n when gpu mode is on the fft grid must not be augmented",&
     223                 :             :     "(n1,n2,n3) = (", n1,n2,n3,") whereas (ldx,ldy,ldz) = (", ldx,ldy,ldz, ")"
     224                 :             :    ABI_ERROR(msg)
     225                 :             :  end if
     226                 :             : 
     227                 :             :  !*************** CUDA INITIALISATION STAGE ****
     228                 :             :  if (fourwf_initialized == 0) then
     229                 :             :    call alloc_ompgpu_fourwf(ngfft,ndat)
     230                 :             :  endif !end of initialisation
     231                 :             : 
     232                 :             : 
     233                 :             :  ! ***********  GPU ALLOCATIONS  ***********************
     234                 :             : 
     235                 :             :  ! If fft size has changed, we realloc our buffers
     236                 :             :  if((nfft_tot/=fft_size_fourwf) .or. (ndat/=ndat_fourwf)) then
     237                 :             :    call free_ompgpu_fourwf()
     238                 :             :    call alloc_ompgpu_fourwf(ngfft,ndat)
     239                 :             :  end if !end if "fft size changed"
     240                 :             : 
     241                 :             :  transfer_fofgin= .not. xomp_target_is_present(c_loc(fofgin))  .and. (option/=3)
     242                 :             :  transfer_fofgout=.not. xomp_target_is_present(c_loc(fofgout)) .and. (option==2 .or. option==3)
     243                 :             :  transfer_denpot =.not. xomp_target_is_present(c_loc(denpot))  .and. (option==2 .or. option==1)
     244                 :             :  transfer_fofr=   .not. xomp_target_is_present(c_loc(fofr))
     245                 :             :  if(l_use_ndo) then
     246                 :             :    transfer_fofginb= .not. xomp_target_is_present(c_loc(fofginb))  .and. (option/=3)
     247                 :             :  end if
     248                 :             : 
     249                 :             :  !$OMP TARGET ENTER DATA MAP(to:fofgin)     IF(transfer_fofgin)
     250                 :             :  !$OMP TARGET ENTER DATA MAP(alloc:fofgout) IF(transfer_fofgout)
     251                 :             :  !$OMP TARGET ENTER DATA MAP(alloc:denpot)  IF(transfer_denpot)
     252                 :             :  !$OMP TARGET ENTER DATA MAP(alloc:fofr)    IF(transfer_fofr)
     253                 :             :  if(l_use_ndo) then
     254                 :             :    !$OMP TARGET ENTER DATA MAP(to:fofginb)     IF(transfer_fofginb)
     255                 :             :    ABI_MALLOC(fofrb, (2,n1,n2,n3*ndat))
     256                 :             :    !$OMP TARGET ENTER DATA MAP(alloc:fofrb)
     257                 :             :  end if
     258                 :             : 
     259                 :             :  if(option==3) then
     260                 :             :    ! We don't want to erase fofr initial value so we alloc a separate array.
     261                 :             :    ABI_MALLOC(work_gpu, (2,n1,n2,n3*ndat))
     262                 :             :    !$OMP TARGET ENTER DATA MAP(alloc:work_gpu)
     263                 :             :  else
     264                 :             :    work_gpu => fofr
     265                 :             :  end if
     266                 :             : 
     267                 :             :  if(option==3) then
     268                 :             :    !$OMP TARGET UPDATE TO(fofr) IF(transfer_fofr)
     269                 :             :  endif
     270                 :             : 
     271                 :             :  if(option==1 .or. option==2) then
     272                 :             :    ! We launch async transfert of denpot
     273                 :             :    !FIXME This async transfer might be better handled through CUDA/HIP after all...
     274                 :             :    ! Issues randomly occurs when using Cray compiler, seems fine with NVHPC.
     275                 :             : #ifdef FC_CRAY
     276                 :             :    !$OMP TARGET UPDATE TO(denpot) IF(transfer_denpot)
     277                 :             : #else
     278                 :             :    !$OMP TARGET UPDATE TO(denpot) NOWAIT IF(transfer_denpot)
     279                 :             : #endif
     280                 :             :    if(option == 1) then
     281                 :             : #ifdef FC_CRAY
     282                 :             :      !$OMP TARGET ENTER DATA MAP(to:weight_r,weight_i)
     283                 :             : #else
     284                 :             :      !$OMP TARGET ENTER DATA MAP(to:weight_r,weight_i) NOWAIT
     285                 :             : #endif
     286                 :             :    endif
     287                 :             :  endif
     288                 :             : 
     289                 :             :  if(option/=3) then
     290                 :             : 
     291                 :             :    ! GPU_SPHERE_IN
     292                 :             : 
     293                 :             :    cfft_size = 2*n1*n2*n3*ndat
     294                 :             : 
     295                 :             :    call gpu_set_to_zero(work_gpu,int(2,c_size_t)*n1*n2*n3*ndat)
     296                 :             : 
     297                 :             :    ! During GPU calculation we do some pre-calculation on symetries
     298                 :             :    if((istwf_k==2) .or. (istwf_k==4) .or. (istwf_k==6) .or. (istwf_k==8)) then
     299                 :             :      shift_inv1 = n1;
     300                 :             :    else
     301                 :             :      shift_inv1 = n1-1;
     302                 :             :    end if
     303                 :             : 
     304                 :             :    if((istwf_k>=2) .and. (istwf_k<=5))  then
     305                 :             :      shift_inv2 = n2;
     306                 :             :    else
     307                 :             :      shift_inv2 = n2-1;
     308                 :             :    end if
     309                 :             : 
     310                 :             :    if((istwf_k==2) .or. (istwf_k==3) .or. (istwf_k==6) .or. (istwf_k==7)) then
     311                 :             :      shift_inv3 = n3;
     312                 :             :    else
     313                 :             :      shift_inv3 = n3-1;
     314                 :             :    end if
     315                 :             : 
     316                 :             : 
     317                 :             :    ! !$OMP TARGET TEAMS DISTRIBUTE MAP(to:work_gpu,kg_kin,fofgin)
     318                 :             :    !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) PRIVATE(i1,i2,i3) MAP(to:work_gpu,kg_kin,fofgin)
     319                 :             :    do idat = 1, ndat
     320                 :             :      !!! $OMP PARALLEL DO PRIVATE(i1,i2,i3)
     321                 :             :      do ipw = 1, npwin
     322                 :             :        i1=kg_kin(1,ipw); if(i1<0)i1=i1+n1; i1=i1+1
     323                 :             :        i2=kg_kin(2,ipw); if(i2<0)i2=i2+n2; i2=i2+1
     324                 :             :        i3=kg_kin(3,ipw); if(i3<0)i3=i3+n3; i3=i3+1
     325                 :             :        ! We write cfft(i1,i2,i3)
     326                 :             :        ! (double2): cfft[i1 + n1*(i2 + n2*(i3 + n3*idat))] = cg[ipw + npw*idat]
     327                 :             :        work_gpu(1, i1, i2, i3+n3*(idat-1)) = fofgin(1, (ipw + npwin*(idat-1)))
     328                 :             :        work_gpu(2, i1, i2, i3+n3*(idat-1)) = fofgin(2, (ipw + npwin*(idat-1)))
     329                 :             :      end do
     330                 :             :    end do
     331                 :             : 
     332                 :             :    if(istwf_k > 1) then
     333                 :             :      if (istwf_k==2 .and. me_g0==1) then
     334                 :             :        !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO MAP(to:work_gpu,fofgin)
     335                 :             :        do idat = 1, ndat
     336                 :             :          work_gpu(1, 1, 1, 1+n3*(idat-1)) = fofgin(1, (1 + npwin*(idat-1)))
     337                 :             :          work_gpu(2, 1, 1, 1+n3*(idat-1)) = zero
     338                 :             :        end do
     339                 :             :      end if
     340                 :             :      ! !$OMP TARGET TEAMS DISTRIBUTE MAP(to:work_gpu,kg_kin,fofgin)
     341                 :             :      !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) PRIVATE(i1,i2,i3,i1inv,i2inv,i3inv) MAP(to:work_gpu,kg_kin,fofgin)
     342                 :             :      do idat = 1, ndat
     343                 :             :        ! !$OMP PARALLEL DO PRIVATE(i1,i2,i3,i1inv,i2inv,i3inv)
     344                 :             :        do ipw = npwmin, npwin
     345                 :             :          i1=kg_kin(1,ipw); if(i1<0)i1=i1+n1;
     346                 :             :          i2=kg_kin(2,ipw); if(i2<0)i2=i2+n2;
     347                 :             :          i3=kg_kin(3,ipw); if(i3<0)i3=i3+n3;
     348                 :             : #if defined HAVE_GPU_CUDA
     349                 :             :          i1inv = modulo(shift_inv1 - i1, n1) + 1
     350                 :             :          i2inv = modulo(shift_inv2 - i2, n2) + 1
     351                 :             :          i3inv = modulo(shift_inv3 - i3, n3) + 1
     352                 :             : #elif defined HAVE_GPU_HIP
     353                 :             :          i1inv = (shift_inv1-i1) - ( ((shift_inv1-i1)/n1) * n1 ) + 1
     354                 :             :          i2inv = (shift_inv2-i2) - ( ((shift_inv2-i2)/n2) * n2 ) + 1
     355                 :             :          i3inv = (shift_inv3-i3) - ( ((shift_inv3-i3)/n3) * n3 ) + 1
     356                 :             : #endif
     357                 :             :          work_gpu(1, i1inv, i2inv, i3inv+n3*(idat-1)) =  fofgin(1, (ipw + npwin*(idat-1)))
     358                 :             :          work_gpu(2, i1inv, i2inv, i3inv+n3*(idat-1)) = -fofgin(2, (ipw + npwin*(idat-1)))
     359                 :             :        end do
     360                 :             :      end do
     361                 :             :    end if
     362                 :             : 
     363                 :             :    ! call backward fourier transform on gpu work_gpu => fofr_gpu
     364                 :             :    !$OMP TARGET DATA USE_DEVICE_ADDR(work_gpu,fofr)
     365                 :             :    call gpu_fft_exec_z2z(FOURWF_ID, c_loc(work_gpu), c_loc(fofr), FFT_INVERSE)
     366                 :             :    !$OMP END TARGET DATA
     367                 :             :    call gpu_fft_stream_synchronize(FOURWF_ID)
     368                 :             : 
     369                 :             :    ! In non-diagonal specific use-case, perform same operation with fofginb:
     370                 :             :    ! - box-to-sphere : fofginb => fofrb
     371                 :             :    ! - backward FFT  : fofrb => fofrb
     372                 :             :    if(l_use_ndo) then
     373                 :             : 
     374                 :             :      call gpu_set_to_zero(fofrb,int(2,c_size_t)*n1*n2*n3*ndat)
     375                 :             : 
     376                 :             :      ! !$OMP TARGET TEAMS DISTRIBUTE MAP(to:fofrb,kg_kin,fofginb)
     377                 :             :      !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) PRIVATE(i1,i2,i3) MAP(to:fofrb,kg_kin,fofginb)
     378                 :             :      do idat = 1, ndat
     379                 :             :        ! !$OMP PARALLEL DO PRIVATE(i1,i2,i3)
     380                 :             :        do ipw = 1, npwin
     381                 :             :          i1=kg_kin(1,ipw); if(i1<0)i1=i1+n1; i1=i1+1
     382                 :             :          i2=kg_kin(2,ipw); if(i2<0)i2=i2+n2; i2=i2+1
     383                 :             :          i3=kg_kin(3,ipw); if(i3<0)i3=i3+n3; i3=i3+1
     384                 :             :          ! We write cfft(i1,i2,i3)
     385                 :             :          ! (double2): cfft[i1 + n1*(i2 + n2*(i3 + n3*idat))] = cg[ipw + npw*idat]
     386                 :             :          fofrb(1, i1, i2, i3+n3*(idat-1)) = fofginb(1, (ipw + npwin*(idat-1)))
     387                 :             :          fofrb(2, i1, i2, i3+n3*(idat-1)) = fofginb(2, (ipw + npwin*(idat-1)))
     388                 :             :        end do
     389                 :             :      end do
     390                 :             : 
     391                 :             :      !$OMP TARGET DATA USE_DEVICE_ADDR(fofrb)
     392                 :             :      call gpu_fft_exec_z2z(FOURWF_ID, c_loc(fofrb), c_loc(fofrb), FFT_INVERSE)
     393                 :             :      !$OMP END TARGET DATA
     394                 :             :      call gpu_fft_stream_synchronize(FOURWF_ID)
     395                 :             :    end if
     396                 :             :  end if
     397                 :             : 
     398                 :             :  if(option==0) then
     399                 :             :    ! We copy back fofr
     400                 :             :    !$OMP TARGET UPDATE from(fofr)    IF(transfer_fofr)
     401                 :             :  end if
     402                 :             : 
     403                 :             :  if(option==1) then
     404                 :             :    ! We finish denpot and weight transferts
     405                 :             :    !!$OMP TASKWAIT depend(in:denpot,weight_r,weight_i)
     406                 :             :    !$OMP TASKWAIT
     407                 :             : 
     408                 :             :    ! Perform density accumulation
     409                 :             : 
     410                 :             :    ! Non-diagonal case
     411                 :             :    if(l_use_ndo) then
     412                 :             : 
     413                 :             :      ! Collapse(4) would lead to race conditions here
     414                 :             :      !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) MAP(to:fofr,fofrb,denpot,weight_r,weight_i)
     415                 :             :      do i3=1, n3
     416                 :             :        do i2=1, n2
     417                 :             :          do i1=1, n1
     418                 :             :            do idat = 1, ndat
     419                 :             :              denpot(i1,i2,i3) = denpot(i1,i2,i3) + weight_r(idat) *&
     420                 :             :              &    (fofr(1, i1, i2, i3+(idat-1)*n3)*fofrb(1, i1, i2, i3+(idat-1)*n3)&
     421                 :             :              &    +fofr(2, i1, i2, i3+(idat-1)*n3)*fofrb(2, i1, i2, i3+(idat-1)*n3))
     422                 :             :              denpot(i1,i2,i3) = denpot(i1,i2,i3) + weight_i(idat) *&
     423                 :             :              &    (fofrb(2, i1, i2, i3+(idat-1)*n3)*fofr(1, i1, i2, i3+(idat-1)*n3)&
     424                 :             :              &    -fofrb(1, i1, i2, i3+(idat-1)*n3)*fofr(2, i1, i2, i3+(idat-1)*n3))
     425                 :             :            end do
     426                 :             :          end do
     427                 :             :        end do
     428                 :             :      end do
     429                 :             : 
     430                 :             :    ! General case
     431                 :             :    else
     432                 :             : 
     433                 :             :      ! Collapse(4) would lead to race conditions here
     434                 :             :      !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) MAP(to:fofr,denpot,weight_r,weight_i)
     435                 :             :      do i3=1, n3
     436                 :             :        do i2=1, n2
     437                 :             :          do i1=1, n1
     438                 :             :            do idat = 1, ndat
     439                 :             :              denpot(i1,i2,i3) = denpot(i1,i2,i3) + fofr(1, i1, i2, i3+(idat-1)*n3)*fofr(1, i1, i2, i3+(idat-1)*n3)*weight_r(idat)
     440                 :             :              denpot(i1,i2,i3) = denpot(i1,i2,i3) + fofr(2, i1, i2, i3+(idat-1)*n3)*fofr(2, i1, i2, i3+(idat-1)*n3)*weight_i(idat)
     441                 :             :            end do
     442                 :             :          end do
     443                 :             :        end do
     444                 :             :      end do
     445                 :             :    end if
     446                 :             : 
     447                 :             :    !$OMP TARGET UPDATE from(denpot) IF(transfer_denpot)
     448                 :             : 
     449                 :             :  end if
     450                 :             : 
     451                 :             :  if(option==2) then
     452                 :             :    ! We finished denpot transfert
     453                 :             :    !!$OMP TASKWAIT depend(in:denpot)
     454                 :             :    !$OMP TASKWAIT
     455                 :             : 
     456                 :             :    ! call gpu routine to  Apply local potential
     457                 :             :    if(cplex==1) then
     458                 :             :      ! !$OMP TARGET TEAMS DISTRIBUTE MAP(to:denpot,fofr)
     459                 :             :      !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(4) PRIVATE(izd, tmp) MAP(to:denpot,fofr)
     460                 :             :      do idat = 1, ndat
     461                 :             :        ! !$OMP PARALLEL DO PRIVATE(izd, tmp) COLLAPSE(3)
     462                 :             :        do i3=1, n3
     463                 :             :          do i2=1, n2
     464                 :             :            do i1=1, n1
     465                 :             :              izd = i3+(idat-1)*n3
     466                 :             :              tmp = denpot(i1,i2,i3)
     467                 :             :              fofr(1, i1, i2, izd) = fofr(1, i1, i2, izd) * tmp
     468                 :             :              fofr(2, i1, i2, izd) = fofr(2, i1, i2, izd) * tmp
     469                 :             :            end do
     470                 :             :          end do
     471                 :             :        end do
     472                 :             :      end do
     473                 :             :    else ! cplex==2
     474                 :             : 
     475                 :             :      ! !$OMP TARGET TEAMS DISTRIBUTE MAP(to:denpot,fofr)
     476                 :             :      !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(4) PRIVATE(tmp) MAP(to:denpot,fofr)
     477                 :             :      do idat = 1, ndat
     478                 :             :        ! !$OMP PARALLEL DO COLLAPSE(3) PRIVATE(tmp)
     479                 :             :        do i3=1, n3
     480                 :             :          do i2=1, n2
     481                 :             :            do i1=1, n1
     482                 :             :              tmp = fofr(1, i1, i2, i3+(idat-1)*n3)
     483                 :             :              fofr(1, i1, i2, i3+(idat-1)*n3) = &
     484                 :             :              fofr(1, i1, i2, i3+(idat-1)*n3) * denpot(2*i1-1,i2,i3) &
     485                 :             :            - fofr(2, i1, i2, i3+(idat-1)*n3) * denpot(2*i1,i2,i3)
     486                 :             : 
     487                 :             :              fofr(2, i1, i2, i3+(idat-1)*n3) = &
     488                 :             :              fofr(2, i1, i2, i3+(idat-1)*n3) * denpot(2*i1-1,i2,i3) &
     489                 :             :              + tmp * denpot(2*i1,i2,i3)
     490                 :             :            end do
     491                 :             :          end do
     492                 :             :        end do
     493                 :             :      end do
     494                 :             :    end if
     495                 :             :  end if
     496                 :             : 
     497                 :             :  if(option==2 .or. option==3) then
     498                 :             : 
     499                 :             :    ! call forward fourier transform on gpu: fofr_gpu ==> work_gpu
     500                 :             :    !$OMP TARGET DATA USE_DEVICE_ADDR(work_gpu,fofr)
     501                 :             :    call gpu_fft_exec_z2z(FOURWF_ID, c_loc(fofr), c_loc(work_gpu), FFT_FORWARD)
     502                 :             :    !$OMP END TARGET DATA
     503                 :             :    call gpu_fft_stream_synchronize(FOURWF_ID)
     504                 :             : 
     505                 :             :    one=1
     506                 :             :    xnorm=one/dble(n1*n2*n3)
     507                 :             :    if (istwf_k==2 .and. me_g0==1) then
     508                 :             :      !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO MAP(to:work_gpu,fofgout)
     509                 :             :      do idat = 1, ndat
     510                 :             :        fofgout (1, 1 + npwout*(idat-1)) = work_gpu(1, 1, 1, 1+n3*(idat-1)) * xnorm
     511                 :             :        fofgout (2, 1 + npwout*(idat-1)) = zero
     512                 :             :      end do
     513                 :             :    end if
     514                 :             : 
     515                 :             :    ! !$OMP TARGET TEAMS DISTRIBUTE MAP(to:work_gpu,kg_kout,fofgout)
     516                 :             :    !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) PRIVATE(i1,i2,i3) MAP(to:work_gpu,kg_kout,fofgout)
     517                 :             :    do idat = 1, ndat
     518                 :             :      ! !$OMP PARALLEL DO PRIVATE(i1,i2,i3)
     519                 :             :      do ipw = npwmin, npwout
     520                 :             :        i1=kg_kout(1,ipw); if(i1<0)i1=i1+n1; i1=i1+1
     521                 :             :        i2=kg_kout(2,ipw); if(i2<0)i2=i2+n2; i2=i2+1
     522                 :             :        i3=kg_kout(3,ipw); if(i3<0)i3=i3+n3; i3=i3+1
     523                 :             : 
     524                 :             :        ! We write cg(ig)
     525                 :             :        fofgout (1, ipw + npwout*(idat-1)) = work_gpu(1, i1, i2, i3+n3*(idat-1)) * xnorm
     526                 :             :        fofgout (2, ipw + npwout*(idat-1)) = work_gpu(2, i1, i2, i3+n3*(idat-1)) * xnorm
     527                 :             :      end do
     528                 :             :    end do
     529                 :             : 
     530                 :             :    !$OMP TARGET UPDATE FROM(fofgout)   IF(transfer_fofgout)
     531                 :             :  end if
     532                 :             : 
     533                 :             :  if(option==1 .or. option==2) then
     534                 :             :    !$OMP TARGET EXIT DATA MAP(delete:denpot)  IF(transfer_denpot)
     535                 :             :    if(option == 1) then
     536                 :             :      !$OMP TARGET EXIT DATA MAP(delete:weight_r,weight_i)
     537                 :             :    endif
     538                 :             :  endif
     539                 :             : 
     540                 :             :  if(option==3) then
     541                 :             :    !$OMP TARGET EXIT DATA MAP(delete:work_gpu)
     542                 :             :    ABI_FREE(work_gpu)
     543                 :             :  end if
     544                 :             : 
     545                 :             :  !$OMP TARGET EXIT DATA MAP(delete:fofgin)  IF(transfer_fofgin)
     546                 :             :  !$OMP TARGET EXIT DATA MAP(delete:fofgout) IF(transfer_fofgout)
     547                 :             :  !$OMP TARGET EXIT DATA MAP(delete:fofr)    IF(transfer_fofr)
     548                 :             : 
     549                 :             :  if(l_use_ndo) then
     550                 :             :    !$OMP TARGET EXIT DATA MAP(delete:fofginb)     IF(transfer_fofginb)
     551                 :             :    !$OMP TARGET EXIT DATA MAP(delete:fofrb)
     552                 :             :    ABI_FREE(fofrb)
     553                 :             :  end if
     554                 :             : 
     555                 :             : end subroutine ompgpu_fourwf
     556                 :             : !!***
     557                 :             : 
     558                 :             : !!****************************************************************************************************************
     559                 :             : !!****************************************************************************************************************
     560                 :             : !!****************************************************************************************************************
     561                 :             : 
     562                 :             : ! Memory allocation routine
     563                 :             : subroutine alloc_ompgpu_fourdp(ngfft, ndat)
     564                 :             :  integer, intent(in) :: ngfft(18), ndat
     565                 :             : 
     566                 :             :  integer :: n1,n2,n3, ldx, ldy, ldz
     567                 :             :  integer, target :: t_fft(3)
     568                 :             : 
     569                 :             :  fourdp_initialized = 1
     570                 :             : 
     571                 :             :  ! Size modification if too little memory allocation
     572                 :             :  n1=ngfft(1)
     573                 :             :  n2=ngfft(2)
     574                 :             :  n3=ngfft(3)
     575                 :             :  ldx = ngfft(4)
     576                 :             :  ldy = ngfft(5)
     577                 :             :  ldz = ngfft(6)
     578                 :             :  fft_size_fourdp=n1*n2*n3
     579                 :             :  ndat_fourdp = ndat
     580                 :             : 
     581                 :             :  ! Initialisation des plans FFT
     582                 :             :  t_fft(1) = n3;
     583                 :             :  t_fft(2) = n2;
     584                 :             :  t_fft(3) = n1;
     585                 :             : 
     586                 :             :  ! Creation du plan
     587                 :             :  call gpu_fft_plan_many(FOURDP_ID, 3, c_loc(t_fft), c_null_ptr, 1, ldx*ldy*ldz, c_null_ptr, 1, ldx*ldy*ldz, FFT_Z2Z, ndat);
     588                 :             : 
     589                 :             : end subroutine alloc_ompgpu_fourdp
     590                 :             : 
     591                 :             : subroutine free_ompgpu_fourdp()
     592                 :             : 
     593                 :             :  if(fourdp_initialized==0) return
     594                 :             : 
     595                 :             :  ! On detruit l'ancien plan
     596                 :             :  call gpu_fft_plan_destroy(FOURDP_ID)
     597                 :             : 
     598                 :             :  fourdp_initialized = 0;
     599                 :             : 
     600                 :             : end subroutine free_ompgpu_fourdp
     601                 :             : 
     602                 :             : subroutine alloc_ompgpu_fourwf(ngfft, ndat)
     603                 :             :  integer, intent(in) :: ngfft(18), ndat
     604                 :             : 
     605                 :             :  integer :: n1,n2,n3, ldx, ldy, ldz
     606                 :             :  integer, target :: t_fft(3),embed(3)
     607                 :             : 
     608                 :             :  fourwf_initialized = 1
     609                 :             : 
     610                 :             :  ! Size modification if too little memory allocation
     611                 :             :  n1=ngfft(1)
     612                 :             :  n2=ngfft(2)
     613                 :             :  n3=ngfft(3)
     614                 :             :  ldx = ngfft(4)
     615                 :             :  ldy = ngfft(5)
     616                 :             :  ldz = ngfft(6)
     617                 :             :  fft_size_fourwf=n1*n2*n3
     618                 :             :  ndat_fourwf = ndat
     619                 :             : 
     620                 :             :  ! Initialisation des plans FFT
     621                 :             :  t_fft(1) = n3;
     622                 :             :  t_fft(2) = n2;
     623                 :             :  t_fft(3) = n1;
     624                 :             : 
     625                 :             :  embed(1) = ldz
     626                 :             :  embed(2) = ldy
     627                 :             :  embed(3) = ldx
     628                 :             : 
     629                 :             :  ! Creation du plan
     630                 :             :  call gpu_fft_plan_many(FOURWF_ID, 3, c_loc(t_fft), c_loc(embed), 1, ldx*ldy*ldz, c_loc(embed), 1, ldx*ldy*ldz, FFT_Z2Z, ndat);
     631                 :             : 
     632                 :             : end subroutine alloc_ompgpu_fourwf
     633                 :             : 
     634                 :             : subroutine free_ompgpu_fourwf()
     635                 :             : 
     636                 :             :  if(fourwf_initialized==0) return
     637                 :             : 
     638                 :             :  ! On detruit l'ancien plan
     639                 :             :  call gpu_fft_plan_destroy(FOURWF_ID)
     640                 :             : 
     641                 :             :  fourwf_initialized = 0
     642                 :             : 
     643                 :             : end subroutine free_ompgpu_fourwf
     644                 :             : 
     645                 :             : #else
     646                 :             : ! interface for unsupported compilers
     647                 :           0 : subroutine ompgpu_fourdp(cplex,ngfft,ldx,ldy,ldz,ndat,isign,fofg,fofr)
     648                 :             : 
     649                 :             : !Arguments ------------------------------------
     650                 :             : !scalars
     651                 :             :  integer,intent(in) :: cplex,ngfft(18),ldx,ldy,ldz,ndat,isign
     652                 :             : !arrays
     653                 :             :  real(dp),intent(inout) :: fofg(2*ldx*ldy*ldz*ndat)
     654                 :             :  real(dp),intent(inout) :: fofr(cplex*ldx*ldy*ldz*ndat)
     655                 :             : 
     656                 :             : ! *************************************************************************
     657                 :             : 
     658                 :             :  ABI_UNUSED((/cplex,ldx,ldy,ldz,ndat,isign/))
     659                 :             :  ABI_UNUSED((/ngfft/))
     660                 :             :  ABI_UNUSED((/fofg,fofr/))
     661                 :             : 
     662                 :           0 : end subroutine ompgpu_fourdp
     663                 :             : 
     664                 :           0 : subroutine ompgpu_fourwf(cplex,denpot,fofgin,fofgout,fofr,gboundin,gboundout,istwf_k,&
     665                 :           0 : &  kg_kin,kg_kout,mgfft,ndat,ngfft,npwin,npwout,ldx,ldy,ldz,option,weight_r,weight_i)
     666                 :             : 
     667                 :             : !Arguments ------------------------------------
     668                 :             : !scalars
     669                 :             :  integer,intent(in) :: cplex,istwf_k,ldx,ldy,ldz,ndat,npwin,npwout,option,mgfft
     670                 :             :  real(dp),intent(in) :: weight_i(:),weight_r(:)
     671                 :             : !arrays
     672                 :             :  integer,intent(in) :: gboundin(2*mgfft+8,2),gboundout(2*mgfft+8,2)
     673                 :             :  integer,intent(in) :: kg_kin(3,npwin),kg_kout(3,npwout),ngfft(18)
     674                 :             :  real(dp),target,intent(inout) :: denpot(cplex*ldx,ldy,ldz)
     675                 :             :  real(dp),intent(in) :: fofgin(2,npwin*ndat)
     676                 :             :  real(dp),intent(inout),target :: fofr(2,ldx,ldy,ldz*ndat)
     677                 :             :  real(dp),intent(out) :: fofgout(2,npwout*ndat)
     678                 :             : 
     679                 :             :  ! Marking unused variables to please code quality checks
     680                 :             :  ABI_UNUSED((/cplex,istwf_k,ldx,ldy,ldz,ndat,npwin,npwout,option,mgfft/))
     681                 :             :  ABI_UNUSED((/weight_i,weight_r/))
     682                 :             :  ABI_UNUSED((/gboundin,gboundout/))
     683                 :             :  ABI_UNUSED((/kg_kin,kg_kout,ngfft/))
     684                 :             :  ABI_UNUSED((/denpot,fofgin,fofgout,fofr/))
     685                 :           0 :  ABI_BUG("Unhandled configuration for OpenMP GPU immplementation")
     686                 :           0 : end subroutine ompgpu_fourwf
     687                 :             : 
     688                 :           0 : subroutine alloc_ompgpu_fourwf(ngfft, ndat)
     689                 :             : !Arguments ------------------------------------
     690                 :             :  integer, intent(in) :: ngfft(6), ndat
     691                 :             : 
     692                 :             :  ABI_UNUSED((/ngfft,ndat/))
     693                 :           0 :  ABI_BUG("Unhandled configuration for OpenMP GPU immplementation")
     694                 :           0 : end subroutine alloc_ompgpu_fourwf
     695                 :             : 
     696                 :           0 : subroutine free_ompgpu_fourwf()
     697                 :           0 :  ABI_BUG("Unhandled configuration for OpenMP GPU immplementation")
     698                 :           0 : end subroutine free_ompgpu_fourwf
     699                 :             : 
     700                 :             : #endif
     701                 :             : 
     702                 :             : end module m_ompgpu_fourwf
     703                 :             : !!***
        

Generated by: LCOV version 2.3-1