LCOV - code coverage report
Current view: top level - src/66_nonlocal - m_gemm_nonlop_projectors.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 64.2 % 475 305
Test Date: 2026-09-21 22:40:37 Functions: 83.3 % 12 10

            Line data    Source code
       1              : !!****m* ABINIT/m_gemm_nonlop_projectors
       2              : !! NAME
       3              : !! m_gemm_nonlop
       4              : !!
       5              : !! FUNCTION
       6              : !!  This module provides functions to compute the nonlocal operator by means of the BLAS GEMM
       7              : !!  routine. By treating ndat simultaneous wavefunctions, it is able to exploit BLAS3 routines,
       8              : !!  which leads to excellent CPU efficiency and OpenMP scalability.
       9              : !!
      10              : !! COPYRIGHT
      11              : !! Copyright (C) 2014-2026 ABINIT group (AL)
      12              : !! This file is distributed under the terms of the
      13              : !! GNU General Public License, see ~abinit/COPYING
      14              : !! or http://www.gnu.org/copyleft/gpl.txt .
      15              : !!
      16              : !! SOURCE
      17              : 
      18              : ! TODO list :
      19              : ! Don't allocate the full nkpt structures, only those that are treated by this proc: use same init as in m_bandfft_kpt
      20              : ! support more options (forces & stresses mostly)
      21              : ! Support RF/other computations (only GS right now)
      22              : ! handle the case where nloalg(2) < 0, ie no precomputation of ph3d
      23              : ! more systematic checking of the workflow (right now, only works if init/make/gemm/destroy, no multiple makes, etc)
      24              : ! Avoid allocating the complex matrix when istwfk > 1
      25              : ! Merge with chebfi's invovl
      26              : 
      27              : 
      28              : #if defined HAVE_CONFIG_H
      29              : #include "config.h"
      30              : #endif
      31              : 
      32              : #include "abi_common.h"
      33              : 
      34              : module m_gemm_nonlop_projectors
      35              : 
      36              :  use defs_basis
      37              :  use m_errors
      38              :  use m_abicore
      39              :  use m_xomp
      40              :  use m_xmpi
      41              :  use m_fstrings,    only : itoa, ftoa, sjoin
      42              :  use m_gputk
      43              :  use m_abi_linalg
      44              : 
      45              :  use defs_abitypes, only : MPI_type
      46              :  use m_kg, only : mkkpg
      47              :  use m_hamiltonian, only : KPRIME_H_K, K_H_KPRIME, K_H_K, KPRIME_H_KPRIME
      48              : 
      49              : #if defined(HAVE_GPU)
      50              :  use m_gpu_toolbox
      51              : #endif
      52              : 
      53              : #if defined(HAVE_GPU_CUDA)
      54              :  use m_alloc_hamilt_gpu, only : gemm_nonlop_gpu_data
      55              : #endif
      56              : 
      57              :  use, intrinsic :: iso_c_binding, only : c_int32_t, c_int64_t, c_float, c_double, c_size_t, c_loc, c_ptr
      58              : 
      59              :  implicit none
      60              : 
      61              :  private
      62              : 
      63              :  public :: init_gemm_nonlop
      64              :  public :: destroy_gemm_nonlop
      65              :  public :: reset_gemm_nonlop
      66              :  public :: set_gemm_nonlop_ikpt
      67              :  public :: prep_projectors
      68              :  public :: prep_dprojectors
      69              :  public :: refresh_projectors
      70              : 
      71              : !!***
      72              : 
      73              : !----------------------------------------------------------------------
      74              : 
      75              : !!****t* m_gemm_nonlop_projectors/gemm_nonlop_type
      76              : !! NAME
      77              : !! gemm_nonlop_type
      78              : !!
      79              : !! FUNCTION
      80              : !! Contains information needed to apply the nonlocal operator
      81              : !!
      82              : !! SOURCE
      83              :  type,public :: gemm_nonlop_type
      84              : 
      85              :    integer :: npw
      86              :    integer :: nprojs
      87              :    integer :: ngrads
      88              :    integer :: ngrads2
      89              : 
      90              :    integer :: nprojs_blk
      91              :    integer :: nprojs_last_blk
      92              : 
      93              :    real(dp), allocatable :: projs(:, :, :)
      94              :    ! (2, npw, nprojs)
      95              : 
      96              :    real(dp), allocatable :: projs_r(:, :, :)
      97              :    ! (1, npw, nprojs)
      98              : 
      99              :    real(dp), allocatable :: projs_i(:, :, :)
     100              :    ! (1, npw, nprojs)
     101              : 
     102              :    real(dp), allocatable :: dprojs(:, :, :)
     103              :    ! (2, npw, nprojs*ngrads)
     104              :    real(dp), allocatable :: dprojs_r(:, :, :)
     105              :    ! (1, npw, nprojs*ngrads)
     106              :    real(dp), allocatable :: dprojs_i(:, :, :)
     107              :    ! (1, npw, nprojs*ngrads)
     108              : 
     109              :    real(dp), allocatable :: d2projs(:, :, :)
     110              :    ! (2, npw, nprojs*ngrads)
     111              : 
     112              :    integer :: idir
     113              :    integer :: ikpt
     114              :    integer :: choice
     115              : 
     116              :  end type gemm_nonlop_type
     117              : !!***
     118              : 
     119              :  type(gemm_nonlop_type), save, public, target :: gemm_nonlop_kpt(2)
     120              :  !(nkpt)
     121              : 
     122              :  integer, save, public :: gemm_nonlop_ikpt_this_proc_being_treated
     123              :  !! This is oh so very crude, but I can't find any other way to do it without passing ikpt deep down to nonlop
     124              : 
     125              :  logical, save, public :: gemm_nonlop_use_gemm = .false.
     126              :  ! Public variable indicating whether we should call gemm_nonlop or fall back to the usual nonlop. Set to false
     127              :  ! in order not to interfere with non-GS calls to nonlop.
     128              : 
     129              :  logical, save, public :: gemm_nonlop_is_distributed = .false.
     130              :  ! Public variable indicating whether we should gemm_nonlop operated in a distributed manner. Set to false by default
     131              :  ! but might be enabled by memory constraints or forced by user through parameters.
     132              : 
     133              :  logical, save, public :: gemm_nonlop_split_choice23 = .false.
     134              :  ! Public variable indicating whether choice 23 computation should be splitted. Set to false by default
     135              :  ! but might be enabled by memory constraints or forced by user through parameters.
     136              : 
     137              :  integer, save :: gemm_nonlop_nblocks = 1
     138              :  ! How many blocks of MPI tasks should the projs arrays be ditributed.
     139              : 
     140              :  integer, save, public :: gemm_nonlop_block_comm = xmpi_comm_null
     141              :  ! MPI communicator for MPI tasks processing the same gemm_nonlop block for projs array distribution
     142              : 
     143              :  integer, save, public :: gemm_nonlop_block_size = 0
     144              :  ! Public variable indicating size of a block (ie: number of MPI tasks in gemm_nonlop_block_comm)
     145              :  ! Default size 0 indicates no distribution at all.
     146              : 
     147              :  integer, save, public :: gemm_nonlop_choice = -1
     148              : 
     149              :  integer, save, public :: gemm_nonlop_gpu_option = ABI_GPU_DISABLED
     150              : 
     151              :  real(dp),save, allocatable, target :: atom_projs(:,:,:)
     152              :  real(dp),save, allocatable, target :: atom_dprojs(:,:,:,:)
     153              :  real(dp),save, allocatable, target :: atom_d2projs(:,:,:,:)
     154              :  integer,save, allocatable, target :: scal(:)
     155              :  integer,save, allocatable, target :: lmn_parity(:)
     156              :  integer, save :: mod__lmnmax, mod__npw, mod__ndprojs, mod__nd2projs
     157              :  ! Work arrays for prep_*projectors functions. Sized after mod__lmnmax, mod__npw and mod__ndprojs.
     158              : 
     159              : #if defined(HAVE_FC_ISO_C_BINDING) && defined(HAVE_GPU_CUDA)
     160              : 
     161              :  type, bind(c), public :: gemm_nonlop_gpu_type
     162              : 
     163              :    integer(kind=c_int32_t) :: npw
     164              :    integer(kind=c_int32_t) :: nprojs
     165              : 
     166              :    ! array of double on GPU, dimensions are (2, npw, nprojs)
     167              :    type(c_ptr) :: projs
     168              : 
     169              :    ! array of double on GPU, dimensions are (1, npw, nprojs)
     170              :    type(c_ptr) :: projs_r
     171              : 
     172              :    ! array of double on GPU, dimensions are (1, npw, nprojs)
     173              :    type(c_ptr) :: projs_i
     174              : 
     175              :  end type gemm_nonlop_gpu_type
     176              : 
     177              :  !! array of size nkpt of sobjects of type gemm_nonlop_gpu_type, array size is nkpt
     178              :  type(gemm_nonlop_gpu_type), save, public, target :: gemm_nonlop_kpt_gpu(2)
     179              :  !(nkpt)
     180              : 
     181              : #endif
     182              : 
     183              : !!***
     184              : 
     185              : !----------------------------------------------------------------------
     186              : 
     187              : contains
     188              : 
     189              : !----------------------------------------------------------------------
     190              : 
     191              : !!****f* m_gemm_nonlop_projectors/init_gemm_nonlop
     192              : !! NAME
     193              : !! init_gemm_nonlop
     194              : !!
     195              : !! FUNCTION
     196              : !! Initalization of the gemm_nonlop_kpt array
     197              : !!
     198              : !! INPUTS
     199              : !! nkpt= number of k-points
     200              : !!
     201              : !! SOURCE
     202           29 :  subroutine init_gemm_nonlop(gpu_option)
     203              : 
     204              :   integer,intent(in) :: gpu_option
     205              : 
     206              : ! *************************************************************************
     207              : 
     208           87 :   gemm_nonlop_kpt(:)%npw = -1
     209           87 :   gemm_nonlop_kpt(:)%nprojs = -1
     210           87 :   gemm_nonlop_kpt(:)%ngrads = -1
     211           87 :   gemm_nonlop_kpt(:)%ngrads2 = -1
     212           87 :   gemm_nonlop_kpt(:)%choice = -1
     213           87 :   gemm_nonlop_kpt(:)%idir = -1
     214           87 :   gemm_nonlop_kpt(:)%ikpt = -1
     215              : 
     216           29 :   if(gpu_option == ABI_GPU_LEGACY .or. gpu_option == ABI_GPU_KOKKOS) then
     217              : #ifdef HAVE_GPU_CUDA
     218              :     gemm_nonlop_kpt_gpu(:)%npw = -1
     219              :     gemm_nonlop_kpt_gpu(:)%nprojs = -1
     220              :     gemm_nonlop_gpu_data % allocated = .false.
     221              : #endif
     222              :   end if
     223              : 
     224           29 :   gemm_nonlop_block_comm=xmpi_comm_null
     225           29 :   gemm_nonlop_block_size=0
     226           29 :   gemm_nonlop_nblocks=1
     227           29 :   gemm_nonlop_gpu_option=gpu_option
     228              : 
     229           29 :  end subroutine init_gemm_nonlop
     230              : !!***
     231              : 
     232              : !----------------------------------------------------------------------
     233              : 
     234              : !!****f* m_gemm_nonlop_projectors/destroy_gemm_nonlop
     235              : !! NAME
     236              : !! destroy_gemm_nonlop
     237              : !!
     238              : !! FUNCTION
     239              : !! Destruction of the gemm_nonlop_kpt array
     240              : !!
     241              : !! INPUTS
     242              : !! nkpt= number of k-points
     243              : !!
     244              : !! SOURCE
     245           29 :  subroutine destroy_gemm_nonlop(gpu_option)
     246              : 
     247              :   integer,intent(in) :: gpu_option
     248              : 
     249              : ! *************************************************************************
     250              : 
     251           29 :   call free_gemm_nonlop_ikpt(1,gpu_option)
     252           29 :   call free_gemm_nonlop_ikpt(2,gpu_option)
     253           29 :   call destroy_work_arrays(gpu_option)
     254           29 :   if(gemm_nonlop_block_comm/=xmpi_comm_null) call xmpi_comm_free(gemm_nonlop_block_comm)
     255              : 
     256           29 :  end subroutine destroy_gemm_nonlop
     257              : !!***
     258              : 
     259              : !----------------------------------------------------------------------
     260              : 
     261              : !!****f* m_gemm_nonlop_projectors/alloc_work_arrays
     262              : !! NAME
     263              : !! alloc_work_arrays
     264              : !!
     265              : !! FUNCTION
     266              : !! Allocation of work arrays
     267              : !!
     268              : !! INPUTS
     269              : !! gpu_option = which GPU code path is used
     270              : !!
     271              : !! SOURCE
     272         1120 :  subroutine alloc_work_arrays(lmnmax,npw,ndprojs,nd2projs,gpu_option)
     273              : 
     274              :   integer,intent(in) :: lmnmax,npw,ndprojs,nd2projs,gpu_option
     275              : 
     276              : ! *************************************************************************
     277              : 
     278              :   !FIXME Would be nice to not allocate/reallocate at each call, but it seem troublesome in practice
     279              :   !if(mod__lmnmax>=lmnmax .and. mod__npw>=npw .and. mod__ndprojs>=ndprojs .and. mod__nd2projs>=nd2projs) then
     280              :   !  return ! Nothing to do
     281              :   !end if
     282              : 
     283         1120 :   call destroy_work_arrays(gpu_option)
     284              : 
     285         4480 :   ABI_MALLOC(atom_projs, (2, npw, lmnmax))
     286         3360 :   ABI_MALLOC(scal, (lmnmax))
     287         2240 :   ABI_MALLOC(lmn_parity, (lmnmax))
     288              : #ifdef HAVE_OPENMP_OFFLOAD
     289              :   !$OMP TARGET ENTER DATA MAP(alloc:atom_projs,scal,lmn_parity) IF(gpu_option==ABI_GPU_OPENMP)
     290              : #endif
     291              : 
     292         1120 :   if(ndprojs>0) then
     293         1060 :     ABI_MALLOC(atom_dprojs, (2, npw, ndprojs, lmnmax))
     294              : #ifdef HAVE_OPENMP_OFFLOAD
     295              :     !$OMP TARGET ENTER DATA MAP(alloc:atom_dprojs) IF(gpu_option==ABI_GPU_OPENMP)
     296              : #endif
     297              :   end if
     298              : 
     299         1120 :   if(nd2projs>0) then
     300            0 :     ABI_MALLOC(atom_d2projs, (2, npw, nd2projs, lmnmax))
     301              : #ifdef HAVE_OPENMP_OFFLOAD
     302              :     !$OMP TARGET ENTER DATA MAP(alloc:atom_d2projs) IF(gpu_option==ABI_GPU_OPENMP)
     303              : #endif
     304              :   end if
     305              : 
     306         1120 :   mod__lmnmax=lmnmax
     307         1120 :   mod__npw=npw
     308         1120 :   mod__ndprojs=ndprojs
     309         1120 :   mod__nd2projs=nd2projs
     310              : 
     311         1120 :  end subroutine alloc_work_arrays
     312              : !!***
     313              : 
     314              : !----------------------------------------------------------------------
     315              : 
     316              : !!****f* m_gemm_nonlop_projectors/destroy_work_arrays
     317              : !! NAME
     318              : !! destroy_work_arrays
     319              : !!
     320              : !! FUNCTION
     321              : !! Destruction of work arrays
     322              : !!
     323              : !! INPUTS
     324              : !! gpu_option = which GPU code path is used
     325              : !!
     326              : !! SOURCE
     327         1149 :  subroutine destroy_work_arrays(gpu_option)
     328              : 
     329              :   integer,intent(in) :: gpu_option
     330              : 
     331              : ! *************************************************************************
     332              :   ABI_UNUSED((/gpu_option/))
     333              : 
     334         1149 :   if(allocated(atom_projs)) then
     335              : #ifdef HAVE_OPENMP_OFFLOAD
     336              :     !$OMP TARGET EXIT DATA MAP(delete:atom_projs) IF(gpu_option==ABI_GPU_OPENMP)
     337              : #endif
     338         1120 :     ABI_FREE(atom_projs)
     339              :   end if
     340         1149 :   if(allocated(atom_dprojs)) then
     341              : #ifdef HAVE_OPENMP_OFFLOAD
     342              :     !$OMP TARGET EXIT DATA MAP(delete:atom_dprojs) IF(gpu_option==ABI_GPU_OPENMP)
     343              : #endif
     344          212 :     ABI_FREE(atom_dprojs)
     345              :   end if
     346         1149 :   if(allocated(atom_d2projs)) then
     347              : #ifdef HAVE_OPENMP_OFFLOAD
     348              :     !$OMP TARGET EXIT DATA MAP(delete:atom_d2projs) IF(gpu_option==ABI_GPU_OPENMP)
     349              : #endif
     350            0 :     ABI_FREE(atom_d2projs)
     351              :   end if
     352         1149 :   if(allocated(scal)) then
     353              : #ifdef HAVE_OPENMP_OFFLOAD
     354              :     !$OMP TARGET EXIT DATA MAP(delete:scal) IF(gpu_option==ABI_GPU_OPENMP)
     355              : #endif
     356         1120 :     ABI_FREE(scal)
     357              :   end if
     358         1149 :   if(allocated(lmn_parity)) then
     359              : #ifdef HAVE_OPENMP_OFFLOAD
     360              :     !$OMP TARGET EXIT DATA MAP(delete:lmn_parity) IF(gpu_option==ABI_GPU_OPENMP)
     361              : #endif
     362         1120 :     ABI_FREE(lmn_parity)
     363              :   end if
     364         1149 :   mod__lmnmax=0
     365         1149 :   mod__npw=0
     366         1149 :   mod__ndprojs=0
     367         1149 :   mod__nd2projs=0
     368              : 
     369         1149 :  end subroutine destroy_work_arrays
     370              : !!***
     371              : 
     372              : !----------------------------------------------------------------------
     373              : 
     374              : !!****f* m_gemm_nonlop_projectors/free_gemm_nonlop_ikpt
     375              : !! NAME
     376              : !! free_destroy_gemm_nonlop_ikpt
     377              : !!
     378              : !! FUNCTION
     379              : !! Release memory for one kpt value of the gemm_nonlop_kpt array
     380              : !!
     381              : !! INPUTS
     382              : !! ikpt= index of gemm_nonlop_kptto be released
     383              : !!
     384              : !! SOURCE
     385         1430 :  subroutine free_gemm_nonlop_ikpt(ik, gpu_option)
     386              : 
     387              :   integer,intent(in) :: ik, gpu_option
     388              : 
     389              : ! *************************************************************************
     390              : 
     391              :  if(gpu_option == ABI_GPU_LEGACY .or. gpu_option == ABI_GPU_KOKKOS) then
     392              : #ifdef HAVE_GPU_CUDA
     393              :    if(gemm_nonlop_kpt_gpu(ik)%nprojs /= -1) then
     394              :      ! deallocate arrays projs, projs_r and projs_i
     395              :      if (allocated(gemm_nonlop_kpt(ik)%projs)) then
     396              :        call dealloc_on_gpu(gemm_nonlop_kpt_gpu(ik)%projs)
     397              :      end if
     398              :      if (allocated(gemm_nonlop_kpt(ik)%projs_r)) then
     399              :        call dealloc_on_gpu(gemm_nonlop_kpt_gpu(ik)%projs_r)
     400              :      end if
     401              :      if (allocated(gemm_nonlop_kpt(ik)%projs_i)) then
     402              :        call dealloc_on_gpu(gemm_nonlop_kpt_gpu(ik)%projs_i)
     403              :      end if
     404              :      gemm_nonlop_kpt_gpu(ik)%nprojs = -1
     405              :      gemm_nonlop_kpt_gpu(ik)%npw = -1
     406              :    end if
     407              : #endif
     408              :  end if
     409              : 
     410              :  if(gpu_option == ABI_GPU_OPENMP) then
     411              : #ifdef HAVE_OPENMP_OFFLOAD
     412              :    call free_ompgpu_current_ikpt(ik)
     413              : #endif
     414              :  end if
     415              : 
     416         1430 :  if(gemm_nonlop_kpt(ik)%nprojs /= -1) then
     417         1372 :    if (allocated(gemm_nonlop_kpt(ik)%projs)) then
     418         1086 :      ABI_FREE(gemm_nonlop_kpt(ik)%projs)
     419              :    end if
     420         1372 :    if (allocated(gemm_nonlop_kpt(ik)%projs_r)) then
     421          286 :      ABI_FREE(gemm_nonlop_kpt(ik)%projs_r)
     422              :    end if
     423         1372 :    if (allocated(gemm_nonlop_kpt(ik)%projs_i)) then
     424          286 :    ABI_FREE(gemm_nonlop_kpt(ik)%projs_i)
     425              :    end if
     426         1372 :    gemm_nonlop_kpt(ik)%nprojs = -1
     427         1372 :    if(gemm_nonlop_kpt(ik)%ngrads /= -1) then
     428          108 :      if (allocated(gemm_nonlop_kpt(ik)%dprojs)) then
     429           87 :        ABI_FREE(gemm_nonlop_kpt(ik)%dprojs)
     430              :      end if
     431          108 :      if (allocated(gemm_nonlop_kpt(ik)%dprojs_r)) then
     432           21 :        ABI_FREE(gemm_nonlop_kpt(ik)%dprojs_r)
     433              :      end if
     434          108 :      if (allocated(gemm_nonlop_kpt(ik)%dprojs_i)) then
     435           21 :        ABI_FREE(gemm_nonlop_kpt(ik)%dprojs_i)
     436              :      end if
     437          108 :      gemm_nonlop_kpt(ik)%ngrads = -1
     438              :    end if
     439         1372 :    if(gemm_nonlop_kpt(ik)%ngrads2 /= -1) then
     440            0 :      if (allocated(gemm_nonlop_kpt(ik)%d2projs)) then
     441            0 :        ABI_FREE(gemm_nonlop_kpt(ik)%d2projs)
     442              :      end if
     443            0 :      gemm_nonlop_kpt(ik)%ngrads2 = -1
     444              :    end if
     445              :  end if
     446         1430 :  gemm_nonlop_kpt(ik)%choice = -1
     447         1430 :  gemm_nonlop_kpt(ik)%idir = -1
     448         1430 :  gemm_nonlop_kpt(ik)%ikpt = -1
     449              : 
     450         1430 :  if(gemm_nonlop_is_distributed) then
     451            0 :    gemm_nonlop_kpt(ik)%nprojs_blk = -1
     452            0 :    gemm_nonlop_kpt(ik)%nprojs_last_blk = -1
     453              :  end if
     454              : 
     455         1430 :  end subroutine free_gemm_nonlop_ikpt
     456              : !!***
     457              : 
     458              : !----------------------------------------------------------------------
     459              : 
     460              :  subroutine free_ompgpu_current_ikpt(ik)
     461              : 
     462              :   integer,intent(in) :: ik
     463              : 
     464              : #ifdef HAVE_OPENMP_OFFLOAD
     465              : 
     466              :   call free_ompgpu_current_ikpt_projs(ik)
     467              :   call free_ompgpu_current_ikpt_dprojs(ik)
     468              : 
     469              : #else
     470              :   ABI_UNUSED((/ik/))
     471              : #endif
     472              :  end subroutine free_ompgpu_current_ikpt
     473              : 
     474              : !----------------------------------------------------------------------
     475              : 
     476              :  subroutine free_ompgpu_current_ikpt_projs(ik)
     477              : 
     478              :   integer,intent(in) :: ik
     479              : #ifdef HAVE_OPENMP_OFFLOAD
     480              :   !NOTE: Those pointers exists to be served to OpenMP TARGET directives to hide
     481              :   !      the datastructure gemm_nonlop_kpt which is not supported in GCC, LLVM and Cray
     482              :   real(dp), ABI_CONTIGUOUS pointer :: gemm_nonlop_kpt_projs_ompptr(:,:,:)
     483              :   real(dp), ABI_CONTIGUOUS pointer :: gemm_nonlop_kpt_projs_r_ompptr(:,:,:)
     484              :   real(dp), ABI_CONTIGUOUS pointer :: gemm_nonlop_kpt_projs_i_ompptr(:,:,:)
     485              : 
     486              : 
     487              :   if(xomp_target_is_present(c_loc(gemm_nonlop_kpt(ik)%projs))) then
     488              :     gemm_nonlop_kpt_projs_ompptr => gemm_nonlop_kpt(ik)%projs
     489              :     !$OMP TARGET EXIT DATA MAP(delete:gemm_nonlop_kpt_projs_ompptr)
     490              :   end if
     491              :   if(xomp_target_is_present(c_loc(gemm_nonlop_kpt(ik)%projs_r))) then
     492              :     gemm_nonlop_kpt_projs_r_ompptr => gemm_nonlop_kpt(ik)%projs_r
     493              :     gemm_nonlop_kpt_projs_i_ompptr => gemm_nonlop_kpt(ik)%projs_i
     494              :     !$OMP TARGET EXIT DATA MAP(delete:gemm_nonlop_kpt_projs_r_ompptr)
     495              :     !$OMP TARGET EXIT DATA MAP(delete:gemm_nonlop_kpt_projs_i_ompptr)
     496              :   end if
     497              : 
     498              : #else
     499              :   ABI_UNUSED((/ik/))
     500              : #endif
     501              :  end subroutine free_ompgpu_current_ikpt_projs
     502              : 
     503              : !----------------------------------------------------------------------
     504              : 
     505              : 
     506              :  subroutine free_ompgpu_current_ikpt_dprojs(ik)
     507              : 
     508              :   integer,intent(in) :: ik
     509              : #ifdef HAVE_OPENMP_OFFLOAD
     510              :   !NOTE: Those pointers exists to be served to OpenMP TARGET directives to hide
     511              :   !      the datastructure gemm_nonlop_kpt which is not supported in GCC, LLVM and Cray
     512              :   real(dp), ABI_CONTIGUOUS pointer :: gemm_nonlop_kpt_dprojs_ompptr(:,:,:)
     513              :   real(dp), ABI_CONTIGUOUS pointer :: gemm_nonlop_kpt_dprojs_r_ompptr(:,:,:)
     514              :   real(dp), ABI_CONTIGUOUS pointer :: gemm_nonlop_kpt_dprojs_i_ompptr(:,:,:)
     515              :   real(dp), ABI_CONTIGUOUS pointer :: gemm_nonlop_kpt_d2projs_ompptr(:,:,:)
     516              : 
     517              :   if(xomp_target_is_present(c_loc(gemm_nonlop_kpt(ik)%dprojs))) then
     518              :     gemm_nonlop_kpt_dprojs_ompptr => gemm_nonlop_kpt(ik)%dprojs
     519              :     !$OMP TARGET EXIT DATA MAP(delete:gemm_nonlop_kpt_dprojs_ompptr)
     520              :   end if
     521              :   if(xomp_target_is_present(c_loc(gemm_nonlop_kpt(ik)%dprojs_i))) then
     522              :     gemm_nonlop_kpt_dprojs_r_ompptr => gemm_nonlop_kpt(ik)%dprojs_r
     523              :     gemm_nonlop_kpt_dprojs_i_ompptr => gemm_nonlop_kpt(ik)%dprojs_i
     524              :     !$OMP TARGET EXIT DATA MAP(delete:gemm_nonlop_kpt_dprojs_r_ompptr)
     525              :     !$OMP TARGET EXIT DATA MAP(delete:gemm_nonlop_kpt_dprojs_i_ompptr)
     526              :   end if
     527              : 
     528              :   if(xomp_target_is_present(c_loc(gemm_nonlop_kpt(ik)%d2projs))) then
     529              :     gemm_nonlop_kpt_d2projs_ompptr => gemm_nonlop_kpt(ik)%d2projs
     530              :     !$OMP TARGET EXIT DATA MAP(delete:gemm_nonlop_kpt_d2projs_ompptr)
     531              :   end if
     532              : 
     533              : #else
     534              :   ABI_UNUSED((/ik/))
     535              : #endif
     536              :  end subroutine free_ompgpu_current_ikpt_dprojs
     537              : 
     538              : !----------------------------------------------------------------------
     539              : 
     540              : !!****f* m_gemm_nonlop_projectors/set_gemm_nonlop_ikpt
     541              : !! NAME
     542              : !! set_gemm_nonlop_ikpt
     543              : !!
     544              : !! FUNCTION
     545              : !! Set the K-point upon which projectors will be computed and
     546              : !! pre-allocate projectors buffers.
     547              : !!
     548              : !! INPUTS
     549              : !! ikpt= K-point id
     550              : !! npw= number of plane-wave
     551              : !! istwf_k=option parameter that describes the storage of wfs
     552              : !! indlmn(6,nlmn)= array giving l,m,n,lm,ln,s for i=lmn
     553              : !! ntypat=number of atoms types
     554              : !! nattyp(ntypat)=number of atoms of each type
     555              : !! gpu_option=which variant of GEMM nonlop is used
     556              : !!
     557              : !! SOURCE
     558          768 :  subroutine set_gemm_nonlop_ikpt(ikpt,npw,istwf_k,indlmn,ntypat,nattyp,gpu_option)
     559              : 
     560              :   integer,intent(in) :: ikpt,istwf_k,npw,ntypat,gpu_option
     561              :   integer,intent(in) :: indlmn(:,:,:), nattyp(ntypat)
     562              : 
     563              :   integer :: nprojs, itypat
     564              : 
     565              : ! *************************************************************************
     566              : 
     567          768 :   gemm_nonlop_ikpt_this_proc_being_treated=ikpt
     568              : 
     569          768 :   nprojs=0
     570         1880 :   do itypat=1,ntypat
     571        17656 :     nprojs = nprojs + count(indlmn(3,:,itypat)>0)*nattyp(itypat)
     572              :   end do
     573              :   ! Call a "dummy" refresh of projectors buffers
     574              :   ! This is mostly a work-around in GPU workloads to ensure there
     575              :   ! is a buffer allocated in GPU memory.
     576          768 :   call refresh_projectors(npw,istwf_k,nprojs,0,0,.false.,gpu_option)
     577              : 
     578          768 :  end subroutine set_gemm_nonlop_ikpt
     579              : !!***
     580              : 
     581              : !!****f* m_gemm_nonlop_projectors/reset_gemm_nonlop
     582              : !! NAME
     583              : !! reset_gemm_nonlop
     584              : !!
     585              : !! FUNCTION
     586              : !! Reset projectors to trigger their recomputation
     587              : !!
     588              : !! INPUTS
     589              : !!
     590              : !! SOURCE
     591          137 :  subroutine reset_gemm_nonlop()
     592              : 
     593              : ! *************************************************************************
     594              : 
     595          411 :   gemm_nonlop_kpt(:)%ikpt   = -1
     596          411 :   gemm_nonlop_kpt(:)%choice = -1
     597          411 :   gemm_nonlop_kpt(:)%idir   = -1
     598              : 
     599          137 :  end subroutine reset_gemm_nonlop
     600              : !!***
     601              : 
     602              : !----------------------------------------------------------------------
     603              : 
     604              : !!****f* m_gemm_nonlop_projectors/refresh_projectors
     605              : !! NAME
     606              : !! prep_projectors
     607              : !!
     608              : !! FUNCTION
     609              : !! Check allocation of projectors arrays for GEMM nonlop, and resize them if need be
     610              : !!
     611              : !! INPUTS
     612              : !!
     613              : !! SOURCE
     614        24960 :  subroutine refresh_projectors(npw,istwf_k,nprojs,ndgxdt,nd2gxdt,&
     615              :  &                             is_kprime,gpu_option)
     616              :   integer,intent(in) :: npw,istwf_k,nprojs,ndgxdt,nd2gxdt,gpu_option
     617              :   logical,intent(in) :: is_kprime
     618              :   integer :: ik,rank,nprojs_blk,nprojs_my_blk,nprojs_last_blk,ierr,nprocs
     619              :   logical :: is_last_rank
     620              : #ifdef HAVE_OPENMP_OFFLOAD
     621              :   !NOTE: Those pointers exists to be served to OpenMP TARGET directives to hide
     622              :   !      the datastructure gemm_nonlop_kpt which is not supported in GCC, LLVM and Cray
     623              :   real(dp), ABI_CONTIGUOUS pointer :: gemm_nonlop_kpt_projs_ompptr(:,:,:)
     624              :   real(dp), ABI_CONTIGUOUS pointer :: gemm_nonlop_kpt_projs_r_ompptr(:,:,:)
     625              :   real(dp), ABI_CONTIGUOUS pointer :: gemm_nonlop_kpt_projs_i_ompptr(:,:,:)
     626              :   real(dp), ABI_CONTIGUOUS pointer :: gemm_nonlop_kpt_dprojs_ompptr(:,:,:)
     627              :   real(dp), ABI_CONTIGUOUS pointer :: gemm_nonlop_kpt_dprojs_r_ompptr(:,:,:)
     628              :   real(dp), ABI_CONTIGUOUS pointer :: gemm_nonlop_kpt_dprojs_i_ompptr(:,:,:)
     629              :   real(dp), ABI_CONTIGUOUS pointer :: gemm_nonlop_kpt_d2projs_ompptr(:,:,:)
     630              : #endif
     631              : 
     632        24960 :   ik=1; if(is_kprime) ik=2
     633              :   if(gemm_nonlop_kpt(ik)%ikpt/=gemm_nonlop_ikpt_this_proc_being_treated &
     634        24960 :   &   .or. npw/=gemm_nonlop_kpt(ik)%npw .or. nprojs/=gemm_nonlop_kpt(ik)%nprojs) then
     635         1372 :     call free_gemm_nonlop_ikpt(ik, gpu_option)
     636              :   end if
     637              : 
     638        24960 :   if(gemm_nonlop_is_distributed) then
     639            0 :     nprocs = xmpi_comm_size(xmpi_world)
     640              :     ! If split size has changed, reset array and init MPI communicator
     641            0 :     if(gemm_nonlop_block_comm==xmpi_comm_null .or. gemm_nonlop_nblocks /= nprocs/gemm_nonlop_block_size) then
     642            0 :       call free_gemm_nonlop_ikpt(ik, gpu_option)
     643            0 :       if(gemm_nonlop_block_comm/=xmpi_comm_null) call xmpi_comm_free(gemm_nonlop_block_comm)
     644            0 :       rank = xmpi_comm_rank(xmpi_world);
     645            0 :       gemm_nonlop_nblocks=nprocs/gemm_nonlop_block_size
     646            0 :       write(std_out,'(A,I3,A,I3,A)')  "Splitting GEMM nonlop projectors on ",&
     647            0 :       &    gemm_nonlop_nblocks, " blocks of ", gemm_nonlop_block_size, " MPI tasks..."
     648            0 :       call xmpi_comm_split(xmpi_world, rank/gemm_nonlop_block_size, rank, gemm_nonlop_block_comm, ierr)
     649            0 :       if(ierr/=0) ABI_BUG("MPI_comm_split failed!")
     650              :     end if
     651              :   end if
     652              : 
     653        24960 :   nprojs_last_blk = nprojs
     654        24960 :   nprojs_my_blk = nprojs
     655        24960 :   nprojs_blk = nprojs
     656        24960 :   rank = 0; is_last_rank = .true.
     657              : 
     658        24960 :   if(gemm_nonlop_block_size > 1) then
     659            0 :     nprojs_blk = nprojs / gemm_nonlop_block_size
     660            0 :     nprojs_last_blk = nprojs_blk + modulo(nprojs,nprojs_blk)
     661              : 
     662            0 :     if(gemm_nonlop_is_distributed) then
     663            0 :       rank = xmpi_comm_rank(gemm_nonlop_block_comm);
     664            0 :       is_last_rank = (rank==gemm_nonlop_block_size-1)
     665              :       if(is_last_rank) then
     666        24960 :         nprojs_my_blk = nprojs_last_blk
     667              :       else
     668            0 :         nprojs_my_blk = nprojs_blk
     669              :       end if
     670              :     end if
     671              :   end if
     672              : 
     673              : 
     674              :   ! Allocation of buffers for 1st and 2nd order derivatives of projectors
     675              :   ! NOTE: those are allocated, if needed, before regular projectors buffers
     676              :   !       for optimization purposes, regarding GPU memory pool.
     677        24960 :   if(nprojs>0) then
     678        24960 :   if(ndgxdt>0) then
     679              :     if(npw/=gemm_nonlop_kpt(ik)%npw .or. nprojs/=gemm_nonlop_kpt(ik)%nprojs &
     680          424 :     &    .or. ndgxdt /= gemm_nonlop_kpt(ik)%ngrads .or. nd2gxdt /=  gemm_nonlop_kpt(ik)%ngrads2) then
     681              :       if(gpu_option == ABI_GPU_OPENMP) call free_ompgpu_current_ikpt_dprojs(ik)
     682          424 :       ABI_SFREE(gemm_nonlop_kpt(ik)%dprojs)
     683          424 :       ABI_SFREE(gemm_nonlop_kpt(ik)%dprojs_r)
     684          424 :       ABI_SFREE(gemm_nonlop_kpt(ik)%dprojs_i)
     685          424 :       ABI_SFREE(gemm_nonlop_kpt(ik)%d2projs)
     686          424 :       gemm_nonlop_kpt(ik)%ngrads = -1
     687          424 :       gemm_nonlop_kpt(ik)%ngrads2 = -1
     688              : 
     689          424 :       if(istwf_k <= 1) then
     690         1216 :         ABI_MALLOC(gemm_nonlop_kpt(ik)%dprojs, (2, npw, nprojs_last_blk*ndgxdt))
     691              : #ifdef HAVE_OPENMP_OFFLOAD
     692              :         gemm_nonlop_kpt_dprojs_ompptr => gemm_nonlop_kpt(ik)%dprojs
     693              :         !$OMP TARGET ENTER DATA MAP(alloc:gemm_nonlop_kpt_dprojs_ompptr) IF(gpu_option==ABI_GPU_OPENMP)
     694              : #endif
     695          304 :         if(nd2gxdt>0) then
     696            0 :           ABI_MALLOC(gemm_nonlop_kpt(ik)%d2projs, (2, npw, nprojs_last_blk*nd2gxdt))
     697              : #ifdef HAVE_OPENMP_OFFLOAD
     698              :           gemm_nonlop_kpt_d2projs_ompptr => gemm_nonlop_kpt(ik)%d2projs
     699              :           !$OMP TARGET ENTER DATA MAP(alloc:gemm_nonlop_kpt_d2projs_ompptr) IF(gpu_option==ABI_GPU_OPENMP)
     700              : #endif
     701              :         end if
     702              :       else
     703          480 :         ABI_MALLOC(gemm_nonlop_kpt(ik)%dprojs_r, (1, npw, nprojs_last_blk*ndgxdt))
     704          360 :         ABI_MALLOC(gemm_nonlop_kpt(ik)%dprojs_i, (1, npw, nprojs_last_blk*ndgxdt))
     705              : #ifdef HAVE_OPENMP_OFFLOAD
     706              :         gemm_nonlop_kpt_dprojs_r_ompptr => gemm_nonlop_kpt(ik)%dprojs_r
     707              :         gemm_nonlop_kpt_dprojs_i_ompptr => gemm_nonlop_kpt(ik)%dprojs_i
     708              :         !$OMP TARGET ENTER DATA MAP(alloc:gemm_nonlop_kpt_dprojs_r_ompptr) IF(gpu_option==ABI_GPU_OPENMP)
     709              :         !$OMP TARGET ENTER DATA MAP(alloc:gemm_nonlop_kpt_dprojs_i_ompptr) IF(gpu_option==ABI_GPU_OPENMP)
     710              : #endif
     711              :       end if
     712              :     end if
     713              :   end if
     714              : 
     715              : 
     716              :   ! Allocation of projectors buffers
     717        24960 :   if(npw/=gemm_nonlop_kpt(ik)%npw .or. nprojs/=gemm_nonlop_kpt(ik)%nprojs) then
     718         1372 :     if(istwf_k <= 1) then
     719         4344 :       ABI_MALLOC(gemm_nonlop_kpt(ik)%projs, (2, npw, nprojs_last_blk))
     720              : #ifdef HAVE_OPENMP_OFFLOAD
     721              :       gemm_nonlop_kpt_projs_ompptr => gemm_nonlop_kpt(ik)%projs
     722              :       !$OMP TARGET ENTER DATA MAP(alloc:gemm_nonlop_kpt_projs_ompptr) IF(gpu_option==ABI_GPU_OPENMP)
     723              : #endif
     724              :     else
     725         1144 :       ABI_MALLOC(gemm_nonlop_kpt(ik)%projs_r, (1, npw, nprojs_last_blk))
     726          858 :       ABI_MALLOC(gemm_nonlop_kpt(ik)%projs_i, (1, npw, nprojs_last_blk))
     727              : #ifdef HAVE_OPENMP_OFFLOAD
     728              :       gemm_nonlop_kpt_projs_r_ompptr => gemm_nonlop_kpt(ik)%projs_r
     729              :       gemm_nonlop_kpt_projs_i_ompptr => gemm_nonlop_kpt(ik)%projs_i
     730              :       !$OMP TARGET ENTER DATA MAP(alloc:gemm_nonlop_kpt_projs_r_ompptr) IF(gpu_option==ABI_GPU_OPENMP)
     731              :       !$OMP TARGET ENTER DATA MAP(alloc:gemm_nonlop_kpt_projs_i_ompptr) IF(gpu_option==ABI_GPU_OPENMP)
     732              : #endif
     733              :     end if
     734              :   end if
     735              :   end if
     736              : 
     737              : 
     738        24960 :   if (nprojs>0) gemm_nonlop_kpt(ik)%nprojs = nprojs
     739        24960 :   if (nprojs>0) gemm_nonlop_kpt(ik)%npw = npw
     740        24960 :   if (ndgxdt>0) gemm_nonlop_kpt(ik)%ngrads = ndgxdt
     741        24960 :   if (nd2gxdt>0) gemm_nonlop_kpt(ik)%ngrads2 = nd2gxdt
     742        24960 :   if(gemm_nonlop_block_size > 1) then
     743            0 :     if(nprojs_blk>0) gemm_nonlop_kpt(ik)%nprojs_blk = nprojs_blk
     744            0 :     if(nprojs_last_blk>0) gemm_nonlop_kpt(ik)%nprojs_last_blk = nprojs_last_blk
     745              :   end if
     746              : 
     747              :   !!!!! CUDA stuff
     748              :   if(gpu_option == ABI_GPU_LEGACY .or. gpu_option == ABI_GPU_KOKKOS) then
     749              : #ifdef HAVE_GPU_CUDA
     750              :     if(gemm_nonlop_kpt_gpu(ik)%nprojs==-1) then
     751              :       gemm_nonlop_kpt_gpu(ik)%npw    = npw
     752              :       gemm_nonlop_kpt_gpu(ik)%nprojs = nprojs
     753              : 
     754              : #ifdef DEBUG_VERBOSE_GPU
     755              :       if(xmpi_comm_rank(xmpi_world) == 0) then
     756              :         call check_gpu_mem("refresh_projectors begin")
     757              :         call wrtout(std_out,sjoin(" npw    .......", itoa(npw)),    'COLL')
     758              :         call wrtout(std_out,sjoin(" nprojs .......", itoa(nprojs)), 'COLL')
     759              :       end if
     760              : #endif
     761              : 
     762              :       if(istwf_k <= 1) then
     763              :         call alloc_on_gpu(gemm_nonlop_kpt_gpu(ik)%projs, INT(2,c_size_t)*npw*nprojs*dp)
     764              :         ! TODO : gradients
     765              :       else
     766              :         call alloc_on_gpu(gemm_nonlop_kpt_gpu(ik)%projs_r, INT(1, c_size_t)*npw*nprojs*dp)
     767              :         call alloc_on_gpu(gemm_nonlop_kpt_gpu(ik)%projs_i, INT(1, c_size_t)*npw*nprojs*dp)
     768              :         ! TODO : gradients
     769              :       end if
     770              : 
     771              : #ifdef DEBUG_VERBOSE_GPU
     772              :       if(xmpi_comm_rank(xmpi_world) == 0) then
     773              :         call check_gpu_mem("refresh_projectors end  ")
     774              :       end if
     775              : #endif
     776              :     end if
     777              : 
     778              : #endif
     779              :   end if
     780        24960 :  end subroutine refresh_projectors
     781              : !!***
     782              : 
     783              : !----------------------------------------------------------------------
     784              : 
     785              : !!****f* m_gemm_nonlop_projectors/prep_projectors
     786              : !! NAME
     787              : !! prep_projectors
     788              : !!
     789              : !! FUNCTION
     790              : !! Prepare projectors array for GEMM nonlop (choice=={0,1})
     791              : !!
     792              : !! INPUTS
     793              : !!
     794              : !! SOURCE
     795          696 :  subroutine prep_projectors(npw,lmnmax,ntypat,indlmn,nattyp,istwf_k,&
     796          696 :  &                          ucvol,ffnl,ph3d,dimffnl,matblk,&
     797              :  &                          nprojs,is_kprime,gpu_option,&
     798              :  &                          iblock)
     799              : 
     800              :   integer, intent(in) :: npw,lmnmax,ntypat,dimffnl,matblk
     801              :   integer, intent(in) :: istwf_k
     802              :   integer, intent(in) :: nprojs,gpu_option,iblock
     803              :   logical, intent(in) :: is_kprime
     804              :   real(dp), intent(in) :: ucvol
     805              :   ! arrays
     806              :   integer, intent(in) :: indlmn(6,lmnmax,ntypat),nattyp(ntypat)
     807              :   real(dp),intent(in),target :: ffnl(npw,dimffnl,lmnmax,ntypat)
     808              :   real(dp),intent(in),target :: ph3d(2,npw,matblk)
     809              : 
     810              :   logical :: map_ffnl,map_ph3d,is_last_rank
     811              :   integer :: il, ipw, ik, ilmn_p, nlmn_p
     812              :   integer :: itypat, ilmn, nlmn, ia, iaph3d, shift, nprojs_my_blk
     813              :   integer :: lmn_beg,ibeg,iend,shift_do,nlmn_o
     814              :   real(dp):: wt,tmp
     815          696 :   real(dp), ABI_CONTIGUOUS pointer ::   projs(:,:,:)
     816          696 :   real(dp), ABI_CONTIGUOUS pointer :: projs_r(:,:,:)
     817          696 :   real(dp), ABI_CONTIGUOUS pointer :: projs_i(:,:,:)
     818              : 
     819            0 :   ik=1; if(is_kprime) ik=2
     820          696 :   if(istwf_k <= 1) then
     821          551 :     projs => gemm_nonlop_kpt(ik)%projs
     822              :   else
     823          145 :     projs_r => gemm_nonlop_kpt(ik)%projs_r
     824          145 :     projs_i => gemm_nonlop_kpt(ik)%projs_i
     825              :   end if
     826              : 
     827          696 :   if(gpu_option==ABI_GPU_OPENMP) then
     828              : 
     829            0 :     if(istwf_k <= 1) then
     830            0 :       call gpu_set_to_zero(projs,int(2,c_size_t)*npw*nprojs)
     831              :     else
     832            0 :       call gpu_set_to_zero(projs_r,int(npw,c_size_t)*nprojs)
     833            0 :       call gpu_set_to_zero(projs_i,int(npw,c_size_t)*nprojs)
     834              :     end if
     835              : 
     836              :   else
     837              : 
     838          696 :     if(istwf_k <= 1) then
     839    330194679 :       projs(:,:,:) = zero
     840              :     else
     841     36945149 :       projs_r(:,:,:) = zero
     842     36945149 :       projs_i(:,:,:) = zero
     843              :     end if
     844              : 
     845              :  end if
     846              : 
     847          696 :   iaph3d = 1
     848          696 :   wt=four_pi/sqrt(ucvol)
     849              : 
     850              :   ! Allocate atom_projs and other work arrays if need be
     851          696 :   call alloc_work_arrays(lmnmax,npw,-1,-1,gpu_option)
     852              : 
     853          696 :   map_ph3d=.false.; map_ffnl=.false.
     854              : #ifdef HAVE_OPENMP_OFFLOAD
     855              :   if(.not. xomp_target_is_present(c_loc(ffnl))) map_ffnl = .true.
     856              :   if(.not. xomp_target_is_present(c_loc(ph3d))) map_ph3d = .true.
     857              :   !$OMP TARGET ENTER DATA MAP(to:ffnl) IF(gpu_option==ABI_GPU_OPENMP .and. map_ffnl)
     858              :   !$OMP TARGET ENTER DATA MAP(to:ph3d) IF(gpu_option==ABI_GPU_OPENMP .and. map_ph3d)
     859              : #endif
     860              : 
     861          696 :   shift = 0
     862          696 :   lmn_beg = 1
     863              : 
     864          696 :   if(gemm_nonlop_block_size > 1) then
     865            0 :     is_last_rank = (iblock==gemm_nonlop_block_size)
     866            0 :     nprojs_my_blk=gemm_nonlop_kpt(ik)%nprojs_blk
     867            0 :     if(is_last_rank) nprojs_my_blk=gemm_nonlop_kpt(ik)%nprojs_last_blk
     868            0 :     ibeg = (iblock-1)*gemm_nonlop_kpt(ik)%nprojs_blk+1
     869            0 :     iend = ibeg+nprojs_my_blk
     870            0 :     shift_do = 0
     871              :   end if
     872              : 
     873         1736 :   do itypat = 1, ntypat
     874        16240 :     nlmn = count(indlmn(3,:,itypat)>0)
     875         1040 :     nlmn_o = nlmn
     876              : 
     877         4224 :     do ia = 1, nattyp(itypat)
     878              : 
     879              :       ! In distributed mode, loops are skipped until reach the section
     880              :       ! of "ilmn" to be stored by local rank
     881         3184 :       if(gemm_nonlop_block_size > 1) then
     882            0 :         if(shift_do+nlmn < ibeg) then
     883            0 :           shift_do = shift_do + nlmn
     884            0 :           iaph3d = iaph3d + 1
     885            0 :           cycle
     886              :         end if
     887              : 
     888            0 :         lmn_beg = max(1,ibeg-shift_do)
     889            0 :         if(shift_do+nlmn > iend - 1) nlmn = iend - shift_do - 1
     890              :       end if
     891              : 
     892              :       !! build atom_projs, from opernlb
     893              :       !! P = 4pi/sqrt(ucvol)* conj(diag(ph3d)) * ffnl * diag(parity), with parity = (-i)^l
     894              : 
     895              :       ! start from 4pi/sqrt(ucvol)*ffnl
     896              :       ! atom_projs(1, :, lmn_beg:nlmn) = four_pi/sqrt(ham%ucvol) * ham%ffnl(:, 1, lmn_beg:nlmn)
     897              :       ! TODO vectorize (DCOPY with stride)
     898         3184 :       if(gpu_option==ABI_GPU_OPENMP) then
     899            0 :         call gpu_set_to_zero(atom_projs,int(2,c_size_t)*npw*lmnmax)
     900              :       else
     901    470590796 :         atom_projs(:,:,:) = zero
     902              :       end if
     903              : #ifdef HAVE_OPENMP_OFFLOAD
     904              :       !$OMP TARGET TEAMS DISTRIBUTE  PARALLEL DO COLLAPSE(2) &
     905              :       !$OMP& PRIVATE(ilmn,ipw) MAP(to:atom_projs,ffnl) &
     906              :       !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
     907              : #endif
     908        45776 :       do ilmn=1,nlmn_o
     909    128567056 :         do ipw=1, npw
     910    128563872 :           atom_projs(1,ipw, ilmn) = wt * ffnl(ipw, 1, ilmn, itypat)
     911              :         end do
     912              :       end do
     913              : 
     914              :       nlmn_p=0
     915              :       ! multiply by (-i)^l
     916        45776 :       do ilmn=1,nlmn_o
     917        42592 :         il=mod(indlmn(1,ilmn, itypat),4);
     918        42592 :         if(.not. (mod(il,2)==0)) then
     919        19104 :           nlmn_p=nlmn_p+1
     920        19104 :           lmn_parity(nlmn_p)=ilmn
     921              :         end if
     922        45776 :         scal(ilmn)=1; if(il>1) scal(ilmn)=-1
     923              :       end do
     924              :       ! multiply by -1
     925         3184 :       if(gpu_option==ABI_GPU_OPENMP) then
     926              : #ifdef HAVE_OPENMP_OFFLOAD
     927              :         !$OMP TARGET UPDATE TO(scal,lmn_parity)
     928              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
     929              :         !$OMP& PRIVATE(ipw,ilmn) MAP(to:atom_projs,scal) &
     930              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
     931              :         do ilmn=1,nlmn_o
     932              :           do ipw=1,npw
     933              :             atom_projs(1,ipw,ilmn) = atom_projs(1,ipw,ilmn) * scal(ilmn)
     934              :             atom_projs(2,ipw,ilmn) = atom_projs(2,ipw,ilmn) * scal(ilmn)
     935              :           end do
     936              :         end do
     937              : #endif
     938              :       else
     939        45776 :         do ilmn=1,nlmn_o
     940    385609616 :           atom_projs(:,:,ilmn) = atom_projs(:,:,ilmn) * scal(ilmn)
     941              :         end do
     942              :       end if
     943              :       ! multiply by -i
     944              : #ifdef HAVE_OPENMP_OFFLOAD
     945              :       !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
     946              :       !$OMP& MAP(to:atom_projs,lmn_parity) PRIVATE(ilmn,ilmn_p,ipw,tmp) &
     947              :       !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
     948              : #endif
     949        22288 :       do ilmn_p=1,nlmn_p
     950     53289268 :         do ipw=1,npw
     951     53266980 :           ilmn=lmn_parity(ilmn_p)
     952     53266980 :           tmp = atom_projs(2,ipw,ilmn)
     953     53266980 :           atom_projs(2,ipw,ilmn) = -atom_projs(1,ipw,ilmn)
     954     53286084 :           atom_projs(1,ipw,ilmn) =  tmp
     955              :         end do
     956              :       end do
     957              : 
     958              :       ! multiply by conj(ph3d)
     959              : #ifdef HAVE_OPENMP_OFFLOAD
     960              :       !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
     961              :       !$OMP& PRIVATE(ilmn,ipw,tmp) MAP(to:atom_projs,ph3d) &
     962              :       !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
     963              : #endif
     964        45776 :       do ilmn=1,nlmn_o
     965    128567056 :         do ipw=1,npw
     966    128521280 :           tmp = atom_projs(1, ipw, ilmn)
     967              :           atom_projs(1, ipw, ilmn) = atom_projs(1, ipw, ilmn) * ph3d(1, ipw, iaph3d) &
     968    128521280 :           &                        + atom_projs(2, ipw, ilmn) * ph3d(2, ipw, iaph3d)
     969              :           atom_projs(2, ipw, ilmn) = atom_projs(2, ipw, ilmn) * ph3d(1, ipw, iaph3d) &
     970    128563872 :           &                        - tmp                      * ph3d(2, ipw, iaph3d)
     971              :         end do
     972              :       end do
     973              : 
     974              :       !! atom_projs is built, copy to projs
     975              : 
     976         3184 :       if(gpu_option==ABI_GPU_OPENMP) then
     977              : #ifdef HAVE_OPENMP_OFFLOAD
     978              :         if(istwf_k <= 1) then
     979              :           !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
     980              :           !$OMP& PRIVATE(ipw,ilmn) MAP(to:projs,atom_projs)
     981              :           do ilmn=1,nlmn-(lmn_beg-1)
     982              :             do ipw=1,npw
     983              :               projs(1, ipw, shift+ilmn) = atom_projs(1, ipw, ilmn+(lmn_beg-1))
     984              :               projs(2, ipw, shift+ilmn) = atom_projs(2, ipw, ilmn+(lmn_beg-1))
     985              :             end do
     986              :           end do
     987              :         else ! istwf_k>1
     988              :           !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
     989              :           !$OMP& PRIVATE(ipw,ilmn) MAP(to:projs_r,projs_i,atom_projs)
     990              :           do ilmn=1,nlmn-(lmn_beg-1)
     991              :             do ipw=1,npw
     992              :               projs_r(1, ipw, shift+ilmn) = atom_projs(1, ipw, ilmn+(lmn_beg-1))
     993              :               projs_i(1, ipw, shift+ilmn) = atom_projs(2, ipw, ilmn+(lmn_beg-1))
     994              :             end do
     995              :           end do
     996              :         end if
     997              : #endif
     998              :       else
     999         3184 :         if(istwf_k <= 1) then
    1000    660390702 :           projs(1:2, :, shift+1:shift+(nlmn-(lmn_beg-1))) = atom_projs(:, :, lmn_beg:nlmn)
    1001              :         else ! istwf_k>1
    1002     36956146 :           projs_r(1, :, shift+1:shift+(nlmn-(lmn_beg-1))) = atom_projs(1, :, lmn_beg:nlmn)
    1003     36956146 :           projs_i(1, :, shift+1:shift+(nlmn-(lmn_beg-1))) = atom_projs(2, :, lmn_beg:nlmn)
    1004              :         end if
    1005              :       end if
    1006              : 
    1007         3184 :       iaph3d = iaph3d + 1
    1008         4224 :       if(gemm_nonlop_block_size > 1) then
    1009            0 :         shift = shift + nlmn - (lmn_beg-1)
    1010            0 :         shift_do = shift_do + nlmn
    1011            0 :         if(shift_do >= iend - 1) exit
    1012              :       else
    1013         3184 :         shift = shift + nlmn
    1014              :       end if
    1015              :     end do
    1016         1736 :     if(gemm_nonlop_block_size > 1 .and. shift_do >= iend - 1) exit
    1017              :   end do
    1018              : 
    1019              : 
    1020              :   !!!!! CUDA stuff
    1021              :   if(gpu_option == ABI_GPU_LEGACY .or. gpu_option == ABI_GPU_KOKKOS) then
    1022              : #ifdef HAVE_GPU_CUDA
    1023              :     ! upload data to gpu memory
    1024              :     if(istwf_k <= 1) then
    1025              :       call copy_on_gpu(gemm_nonlop_kpt(ik)%projs, gemm_nonlop_kpt_gpu(ik)%projs, INT(2, c_size_t)*npw*nprojs*dp)
    1026              :       ! TODO : gradients
    1027              :     else
    1028              :       call copy_on_gpu(gemm_nonlop_kpt(ik)%projs_r, gemm_nonlop_kpt_gpu(ik)%projs_r, &
    1029              :         &                    INT(1, c_size_t)*npw*nprojs*dp)
    1030              :       call copy_on_gpu(gemm_nonlop_kpt(ik)%projs_i, gemm_nonlop_kpt_gpu(ik)%projs_i, &
    1031              :         &                    INT(1, c_size_t)*npw*nprojs*dp)
    1032              :     end if
    1033              : #endif
    1034              :   end if
    1035              : 
    1036              : #ifdef HAVE_OPENMP_OFFLOAD
    1037              :   !$OMP TARGET EXIT DATA MAP(delete:ffnl) IF(gpu_option==ABI_GPU_OPENMP .and. map_ffnl)
    1038              :   !$OMP TARGET EXIT DATA MAP(delete:ph3d) IF(gpu_option==ABI_GPU_OPENMP .and. map_ph3d)
    1039              : #endif
    1040              : 
    1041          696 :  end subroutine prep_projectors
    1042              : !!***
    1043              : 
    1044              : !----------------------------------------------------------------------
    1045              : 
    1046              : !!****f* m_gemm_nonlop_projectors/prep_dprojectors
    1047              : !! NAME
    1048              : !! prep_projectors
    1049              : !!
    1050              : !! FUNCTION
    1051              : !! Prepare projectors' derivatives for given choice (choice={2,3,4,5,51,54,55})
    1052              : !!
    1053              : !! INPUTS
    1054              : !!
    1055              : !! SOURCE
    1056          424 :  subroutine prep_dprojectors(npw,lmnmax,ntypat,indlmn,nattyp,istwf_k,&
    1057          424 :  &                          ucvol,ffnl,ph3d,kpg,nkpg,dimffnl,matblk,&
    1058              :  &                          nprojs,ngrads,ngrads2,choice,signs,idir_pert,&
    1059              :  &                          is_kprime,gpu_option,iblock)
    1060              : 
    1061              :   integer, intent(in) :: npw,lmnmax,ntypat,nkpg,dimffnl,matblk
    1062              :   integer, intent(in) :: istwf_k,iblock
    1063              :   integer, intent(in) :: nprojs,ngrads,ngrads2,choice,signs,idir_pert,gpu_option
    1064              :   logical, intent(in) :: is_kprime
    1065              :   real(dp), intent(in) :: ucvol
    1066              :   ! arrays
    1067              :   integer, intent(in) :: indlmn(6,lmnmax,ntypat),nattyp(ntypat)
    1068              :   real(dp), intent(in), target :: ffnl(npw,dimffnl,lmnmax,ntypat)
    1069              :   real(dp), intent(in), target :: ph3d(2,npw,matblk)
    1070              :   real(dp), intent(in), target :: kpg(npw,nkpg)
    1071              : 
    1072              :   logical :: map_ffnl,map_ph3d,is_last_rank
    1073              :   integer,parameter :: alpha(6)=(/1,2,3,3,3,2/),beta(6)=(/1,2,3,2,1,1/)
    1074              :   integer,parameter :: gamma(3,3)=reshape((/1,6,5,6,2,4,5,4,3/),(/3,3/))
    1075              :   integer :: ndprojs, nd2projs, ilmn_p, nlmn_p
    1076              :   integer :: il, ipw, ik, idir, idir1, idir2, jdir1, jdir2, kdir1, kdir2, ldir1, ldir2, ldir3, ldir4, ffnl_dir
    1077              :   integer :: itypat, ilmn, nlmn, ia, iaph3d, igrad, shift, shift_grad, shift_grad2
    1078              :   integer :: lmn_beg,ibeg,iend,shift_do,nlmn_o,lmn_grad_beg,nprojs_my_blk
    1079              :   real(dp), parameter :: two_pi2=two_pi*two_pi
    1080              :   real(dp):: wt,tmp
    1081          424 :   real(dp), ABI_CONTIGUOUS pointer :: projs  (:,:,:)  ,dprojs(:,:,:)  ,d2projs(:,:,:)
    1082          424 :   real(dp), ABI_CONTIGUOUS pointer :: projs_r(:,:,:),dprojs_r(:,:,:)
    1083          424 :   real(dp), ABI_CONTIGUOUS pointer :: projs_i(:,:,:),dprojs_i(:,:,:)
    1084              : 
    1085              : 
    1086            0 :   ik=1; if(is_kprime) ik=2
    1087          424 :   if(istwf_k <= 1) then
    1088          304 :     projs => gemm_nonlop_kpt(ik)%projs
    1089          304 :     dprojs => gemm_nonlop_kpt(ik)%dprojs
    1090          304 :     if(ngrads2 > 0) then
    1091            0 :       d2projs => gemm_nonlop_kpt(ik)%d2projs
    1092              :     end if
    1093              :   else
    1094          120 :     projs_r => gemm_nonlop_kpt(ik)%projs_r
    1095          120 :     projs_i => gemm_nonlop_kpt(ik)%projs_i
    1096          120 :     dprojs_r => gemm_nonlop_kpt(ik)%dprojs_r
    1097          120 :     dprojs_i => gemm_nonlop_kpt(ik)%dprojs_i
    1098              :   end if
    1099              : 
    1100          424 :   if(gpu_option==ABI_GPU_OPENMP) then
    1101              : 
    1102            0 :     if(istwf_k <= 1) then
    1103            0 :       call gpu_set_to_zero(dprojs,int(2,c_size_t)*npw*nprojs*ngrads)
    1104            0 :       if(ngrads2 > 0) then
    1105            0 :         call gpu_set_to_zero(d2projs,int(2,c_size_t)*npw*nprojs*ngrads2)
    1106              :       end if
    1107              :     else
    1108            0 :       call gpu_set_to_zero(dprojs_r,int(npw,c_size_t)*nprojs*ngrads)
    1109            0 :       call gpu_set_to_zero(dprojs_i,int(npw,c_size_t)*nprojs*ngrads)
    1110              :     end if
    1111              : 
    1112              :   else
    1113              : 
    1114          424 :     if(istwf_k <= 1) then
    1115    395458864 :       dprojs(:,:,:) = zero
    1116          304 :       if(ngrads2 > 0) then
    1117            0 :         d2projs(:,:,:) = zero
    1118              :       end if
    1119              :     else
    1120     47384544 :       dprojs_r(:,:,:) = zero
    1121     47384544 :       dprojs_i(:,:,:) = zero
    1122              :     end if
    1123              : 
    1124              :   end if
    1125              : 
    1126          424 :   iaph3d = 1
    1127          424 :   wt=four_pi/sqrt(ucvol)
    1128          424 :   ffnl_dir=1; if(dimffnl>2) ffnl_dir=idir_pert
    1129              : 
    1130          424 :   ndprojs = 0
    1131          424 :   if (signs==1 .and. (choice==3 .or. choice==23 .or. choice==54 .or. choice==55 .or. choice==6)) then
    1132          212 :     ndprojs = 3
    1133          212 :   else if(signs==2 .and. (choice==5 .or. choice==51 .or. choice==3)) then
    1134            0 :     ndprojs = 1
    1135              :   end if
    1136          424 :   nd2projs = 0
    1137          424 :   if(signs==1 .and. choice==54) then
    1138            0 :     nd2projs = 3
    1139          424 :   else if(signs==1 .and. choice==55) then
    1140            0 :     nd2projs = 6
    1141          424 :   else if(signs==1 .and. choice==6) then
    1142            0 :     nd2projs = 10
    1143              :   end if
    1144              : 
    1145              :   ! Allocate atom_projs and other work arrays if need be
    1146          424 :   call alloc_work_arrays(lmnmax,npw,ndprojs,nd2projs,gpu_option)
    1147              : 
    1148          424 :   map_ph3d=.false.; map_ffnl=.false.
    1149          424 :   if(.not. xomp_target_is_present(c_loc(ffnl))) map_ffnl = .true.
    1150          424 :   if(.not. xomp_target_is_present(c_loc(ph3d))) map_ph3d = .true.
    1151              : #ifdef HAVE_OPENMP_OFFLOAD
    1152              :   !$OMP TARGET ENTER DATA MAP(to:ffnl) IF(gpu_option==ABI_GPU_OPENMP .and. map_ffnl)
    1153              :   !$OMP TARGET ENTER DATA MAP(to:ph3d) IF(gpu_option==ABI_GPU_OPENMP .and. map_ph3d)
    1154              :   !!$OMP TARGET ENTER DATA MAP(to:kpg)  IF(gpu_option==ABI_GPU_OPENMP)
    1155              : #endif
    1156              : 
    1157          424 :   shift = 0 ; shift_grad = 0; shift_grad2 = 0
    1158          424 :   lmn_beg = 1
    1159              : 
    1160          424 :   if(gemm_nonlop_block_size > 1) then
    1161            0 :     is_last_rank = (iblock==gemm_nonlop_block_size)
    1162            0 :     nprojs_my_blk=gemm_nonlop_kpt(ik)%nprojs_blk
    1163            0 :     if(is_last_rank) nprojs_my_blk=gemm_nonlop_kpt(ik)%nprojs_last_blk
    1164            0 :     ibeg = (iblock-1)*gemm_nonlop_kpt(ik)%nprojs_blk+1
    1165            0 :     iend = ibeg+nprojs_my_blk
    1166            0 :     shift_do = 0
    1167            0 :     lmn_grad_beg = -1
    1168              : 
    1169              :   end if
    1170              : 
    1171         1136 :   do itypat = 1, ntypat
    1172        12168 :     nlmn = count(indlmn(3,:,itypat)>0)
    1173          712 :     nlmn_o = nlmn
    1174              : 
    1175         2008 :     do ia = 1, nattyp(itypat)
    1176              : 
    1177              :       ! In distributed mode, loops are skipped until reach the section
    1178              :       ! of "ilmn" to be stored by local rank
    1179         1296 :       if(gemm_nonlop_block_size > 1) then
    1180            0 :         if(shift_do+nlmn < ibeg) then
    1181            0 :           shift_do = shift_do + nlmn
    1182            0 :           iaph3d = iaph3d + 1
    1183            0 :           cycle
    1184              :         end if
    1185              : 
    1186            0 :         lmn_beg = max(1,ibeg-shift_do)
    1187              :         if(lmn_grad_beg==-1) lmn_grad_beg = (lmn_beg-1)*ngrads
    1188            0 :         if(shift_do+nlmn > iend - 1) nlmn = iend - shift_do - 1
    1189              :       end if
    1190              : 
    1191              :       !! build atom_dprojs, from opernlb
    1192              :       !! P = 4pi/sqrt(ucvol)* conj(diag(ph3d)) * ffnl * diag(parity), with parity = (-i)^l
    1193              : 
    1194              :       ! start from 4pi/sqrt(ucvol)*ffnl
    1195         1296 :       if(gpu_option==ABI_GPU_OPENMP) then
    1196            0 :         if (ndprojs>0) then
    1197            0 :           call gpu_set_to_zero(atom_dprojs,int(2,c_size_t)*npw*ndprojs*lmnmax)
    1198            0 :           if(ngrads2>0) then
    1199            0 :             call gpu_set_to_zero(atom_d2projs,int(2,c_size_t)*npw*nd2projs*lmnmax)
    1200              :           end if
    1201              :         end if
    1202              :       else
    1203    186112580 :         if (ndprojs>0) atom_dprojs(:,:,:,:) = zero
    1204         1296 :         if (nd2projs>0) atom_d2projs(:,:,:,:) = zero
    1205              :       end if
    1206         1296 :       if (signs==1 .and. (choice==3 .or. choice==23 .or. choice==54 .or. choice==55 .or. choice==6)) then
    1207              : #ifdef HAVE_OPENMP_OFFLOAD
    1208              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1209              :         !$OMP& PRIVATE(ilmn,idir,ipw) MAP(to:atom_dprojs,ffnl) &
    1210              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1211              : #endif
    1212         9992 :         do ilmn=1,nlmn_o
    1213        38024 :           do idir=1,ndprojs
    1214     51863912 :             do ipw=1, npw
    1215     51854568 :               atom_dprojs(1, ipw, idir, ilmn) = wt * ffnl(ipw, idir+1, ilmn, itypat)
    1216              :             end do
    1217              :           end do
    1218              :         end do
    1219              :       end if
    1220         1296 :       if (signs==2 .and. (choice==3 .or. choice==5 .or. choice==51)) then
    1221              : #ifdef HAVE_OPENMP_OFFLOAD
    1222              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
    1223              :         !$OMP& PRIVATE(ilmn,ipw) MAP(to:atom_dprojs,ffnl) &
    1224              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1225              : #endif
    1226            0 :         do ilmn=1,nlmn_o
    1227         1296 :           do ipw=1, npw
    1228            0 :             atom_dprojs(1, ipw, 1, ilmn) = wt * ffnl(ipw, 1+ffnl_dir, ilmn, itypat)
    1229              :           end do
    1230              :         end do
    1231              :       end if
    1232         1296 :       if(signs==1 .and. choice==54) then
    1233              : #ifdef HAVE_OPENMP_OFFLOAD
    1234              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1235              :         !$OMP& PRIVATE(ilmn,idir,ipw) MAP(to:atom_d2projs,ffnl) &
    1236              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1237              : #endif
    1238            0 :         do ilmn=1,nlmn_o
    1239            0 :           do idir=1,nd2projs
    1240            0 :             do ipw=1, npw
    1241            0 :               atom_d2projs(1, ipw, idir, ilmn) = wt * ffnl(ipw, idir+1, ilmn, itypat)
    1242              :             end do
    1243              :           end do
    1244              :         end do
    1245         1296 :       else if(signs==1 .and. choice==55) then
    1246              : #ifdef HAVE_OPENMP_OFFLOAD
    1247              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1248              :         !$OMP& PRIVATE(ilmn,idir,ipw) MAP(to:atom_d2projs,ffnl) &
    1249              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1250              : #endif
    1251            0 :         do ilmn=1,nlmn_o
    1252            0 :           do idir=1,nd2projs
    1253            0 :             do ipw=1, npw
    1254            0 :               atom_d2projs(1, ipw, idir, ilmn) = wt * ffnl(ipw, idir+4, ilmn, itypat)
    1255              :             end do
    1256              :           end do
    1257              :         end do
    1258         1296 :       else if(signs==1 .and. choice==6) then
    1259              : #ifdef HAVE_OPENMP_OFFLOAD
    1260              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1261              :         !$OMP& PRIVATE(ilmn,idir,ipw) MAP(to:atom_d2projs,ffnl) &
    1262              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1263              : #endif
    1264            0 :         do ilmn=1,nlmn_o
    1265            0 :           do idir=1,10
    1266            0 :             do ipw=1, npw
    1267            0 :               atom_d2projs(1, ipw, idir, ilmn) = wt * ffnl(ipw, idir, ilmn, itypat)
    1268              :             end do
    1269              :           end do
    1270              :         end do
    1271              :       end if
    1272              : 
    1273         1296 :       nlmn_p=0
    1274              :       ! multiply by (-i)^l
    1275         1296 :       if (ndprojs>0) then
    1276         9992 :         do ilmn=1,nlmn_o
    1277         9344 :           il=mod(indlmn(1,ilmn, itypat),4);
    1278         9344 :           if(.not. (mod(il,2)==0)) then
    1279         3888 :             nlmn_p=nlmn_p+1
    1280         3888 :             lmn_parity(nlmn_p)=ilmn
    1281              :           end if
    1282         9992 :           scal(ilmn)=1; if(il>1) scal(ilmn)=-1
    1283              :         end do
    1284              :         ! multiply by -1
    1285          648 :         if(gpu_option==ABI_GPU_OPENMP) then
    1286              : #ifdef HAVE_OPENMP_OFFLOAD
    1287              :           !$OMP TARGET UPDATE TO(scal,lmn_parity)
    1288              :           !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1289              :           !$OMP& PRIVATE(ilmn,idir,ipw) MAP(to:atom_dprojs,scal) &
    1290              :           !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1291              :           do ilmn=1,nlmn_o
    1292              :             do idir=1,ndprojs
    1293              :               do ipw=1,npw
    1294              :                 atom_dprojs(1,ipw,idir,ilmn) = atom_dprojs(1,ipw,idir,ilmn) * scal(ilmn)
    1295              :                 atom_dprojs(2,ipw,idir,ilmn) = atom_dprojs(2,ipw,idir,ilmn) * scal(ilmn)
    1296              :               end do
    1297              :             end do
    1298              :           end do
    1299              :           if(nd2projs>0) then
    1300              :             !$OMP TARGET TEAMS DISTRIBUTE &
    1301              :             !$OMP& PRIVATE(ilmn) MAP(to:atom_d2projs,scal) &
    1302              :             !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1303              :             do ilmn=1,nlmn_o
    1304              :               !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(idir,ipw)
    1305              :               do idir=1,nd2projs
    1306              :                 do ipw=1,npw
    1307              :                   atom_d2projs(1,ipw,idir,ilmn) = atom_d2projs(1,ipw,idir,ilmn) * scal(ilmn)
    1308              :                   atom_d2projs(2,ipw,idir,ilmn) = atom_d2projs(2,ipw,idir,ilmn) * scal(ilmn)
    1309              :                 end do
    1310              :               end do
    1311              :             end do
    1312              :           end if
    1313              : #endif
    1314              :         else
    1315         9992 :           do ilmn=1,nlmn_o
    1316    155517632 :             atom_dprojs(:,:,:,ilmn) = atom_dprojs(:,:,:,ilmn) * scal(ilmn)
    1317              :           end do
    1318          648 :           if(nd2projs>0) then
    1319            0 :             do ilmn=1,nlmn_o
    1320            0 :               atom_d2projs(:,:,:,ilmn) = atom_d2projs(:,:,:,ilmn) * scal(ilmn)
    1321              :             end do
    1322              :           end if
    1323              :         end if
    1324              :         ! multiply by -i
    1325              : #ifdef HAVE_OPENMP_OFFLOAD
    1326              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1327              :         !$OMP MAP(to:atom_dprojs,lmn_parity) PRIVATE(ilmn,ilmn_p,idir,ipw,tmp) &
    1328              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1329              : #endif
    1330         4536 :         do ilmn_p=1,nlmn_p
    1331        16200 :           do idir=1,ndprojs
    1332     21157164 :             do ipw=1,npw
    1333     21141612 :               ilmn=lmn_parity(ilmn_p)
    1334     21141612 :               tmp = atom_dprojs(2,ipw,idir,ilmn)
    1335     21141612 :               atom_dprojs(2,ipw,idir,ilmn) = -atom_dprojs(1,ipw,idir,ilmn)
    1336     21153276 :               atom_dprojs(1,ipw,idir,ilmn) =  tmp
    1337              :             end do
    1338              :           end do
    1339              :         end do
    1340          648 :         if(ngrads2>0) then
    1341              : #ifdef HAVE_OPENMP_OFFLOAD
    1342              :           !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1343              :           !$OMP& MAP(to:atom_d2projs) PRIVATE(idir,ipw,ilmn) &
    1344              :           !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1345              : #endif
    1346            0 :           do ilmn=1,nlmn_o
    1347            0 :             do idir=1,nd2projs
    1348            0 :               do ipw=1,npw
    1349            0 :                 atom_d2projs(1,ipw,idir,ilmn) = -atom_d2projs(1,ipw,idir,ilmn)
    1350            0 :                 atom_d2projs(2,ipw,idir,ilmn) = -atom_d2projs(2,ipw,idir,ilmn)
    1351              :               end do
    1352              :             end do
    1353              :           end do
    1354              : #ifdef HAVE_OPENMP_OFFLOAD
    1355              :           !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1356              :           !$OMP& MAP(to:atom_d2projs,lmn_parity) PRIVATE(ilmn,ilmn_p,idir,ipw,tmp) &
    1357              :           !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1358              : #endif
    1359            0 :           do ilmn_p=1,nlmn_p
    1360            0 :             do idir=1,nd2projs
    1361            0 :               do ipw=1,npw
    1362            0 :                 ilmn=lmn_parity(ilmn_p)
    1363            0 :                 tmp = atom_d2projs(2,ipw,idir,ilmn)
    1364            0 :                 atom_d2projs(2,ipw,idir,ilmn) = -atom_d2projs(1,ipw,idir,ilmn)
    1365            0 :                 atom_d2projs(1,ipw,idir,ilmn) =  tmp
    1366              :               end do
    1367              :             end do
    1368              :           end do
    1369              :         end if
    1370              :       end if
    1371              : 
    1372              :       ! multiply by conj(ph3d)
    1373         1296 :       if (ndprojs>0) then
    1374              : #ifdef HAVE_OPENMP_OFFLOAD
    1375              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1376              :         !$OMP& PRIVATE(ilmn,tmp,ipw,idir) MAP(to:atom_dprojs,ph3d) &
    1377              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1378              : #endif
    1379         9992 :         do ilmn=1,nlmn_o
    1380        38024 :           do idir=1,ndprojs
    1381     51863912 :             do ipw=1,npw
    1382     51826536 :               tmp = atom_dprojs(1, ipw, idir,ilmn)
    1383              :               atom_dprojs(1, ipw, idir,ilmn) = atom_dprojs(1, ipw, idir,ilmn) * ph3d(1, ipw, iaph3d) &
    1384     51826536 :               &                              + atom_dprojs(2, ipw, idir,ilmn) * ph3d(2, ipw, iaph3d)
    1385              :               atom_dprojs(2, ipw, idir,ilmn) = atom_dprojs(2, ipw, idir,ilmn) * ph3d(1, ipw, iaph3d) &
    1386     51854568 :               &                              - tmp                 * ph3d(2, ipw, iaph3d)
    1387              :             end do
    1388              :           end do
    1389              :         end do
    1390              :       end if
    1391         1296 :       if (nd2projs>0) then
    1392              : #ifdef HAVE_OPENMP_OFFLOAD
    1393              :         !$OMP TARGET TEAMS DISTRIBUTE &
    1394              :         !$OMP& PRIVATE(ilmn,idir,ipw,tmp) MAP(to:atom_d2projs,ph3d) &
    1395              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1396              : #endif
    1397            0 :         do ilmn=1,nlmn_o
    1398              :           !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(ipw,idir,tmp)
    1399            0 :           do idir=1,nd2projs
    1400            0 :             do ipw=1,npw
    1401            0 :               tmp = atom_d2projs(1, ipw, idir,ilmn)
    1402              :               atom_d2projs(1, ipw, idir,ilmn) = atom_d2projs(1, ipw, idir,ilmn) * ph3d(1, ipw, iaph3d) &
    1403            0 :               &                               + atom_d2projs(2, ipw, idir,ilmn) * ph3d(2, ipw, iaph3d)
    1404              :               atom_d2projs(2, ipw, idir,ilmn) = atom_d2projs(2, ipw, idir,ilmn) * ph3d(1, ipw, iaph3d) &
    1405            0 :               &                               - tmp                 * ph3d(2, ipw, iaph3d)
    1406              :             end do
    1407              :           end do
    1408              :         end do
    1409              :       end if
    1410              : 
    1411              :       !! Handling dprojs
    1412              : 
    1413         1296 :       if(signs==1 .and. (choice==3 .or. choice==23 .or. choice==55 .or. choice==6)) then
    1414          648 :         if(istwf_k <= 1) then
    1415              : #ifdef HAVE_OPENMP_OFFLOAD
    1416              :           !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1417              :           !$OMP& PRIVATE(ilmn,ipw,idir,idir1,idir2) MAP(to:atom_dprojs,dprojs,kpg) &
    1418              :           !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1419              : #endif
    1420         7088 :           do ilmn=lmn_beg,nlmn
    1421        46784 :             do idir=1,6
    1422     87912760 :               do ipw=1,npw
    1423     87866448 :                 idir1=alpha(idir);idir2=beta(idir)
    1424              :                 dprojs(1, ipw, shift_grad+(ilmn-lmn_beg)*ngrads+idir) = &
    1425              :                 &     -half*(atom_dprojs(1, ipw, idir1, ilmn)*kpg(ipw,idir2) &
    1426     87866448 :                 &     +atom_dprojs(1, ipw, idir2, ilmn)*kpg(ipw,idir1))
    1427              :                 dprojs(2, ipw, shift_grad+(ilmn-lmn_beg)*ngrads+idir) = &
    1428              :                 &     -half*(atom_dprojs(2, ipw, idir1, ilmn)*kpg(ipw,idir2) &
    1429     87906144 :                 &     +atom_dprojs(2, ipw, idir2, ilmn)*kpg(ipw,idir1))
    1430              :               end do
    1431              :             end do
    1432              :           end do
    1433              :         else ! istwf_k>1
    1434              : #ifdef HAVE_OPENMP_OFFLOAD
    1435              :           !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1436              :           !$OMP& PRIVATE(ilmn,ipw,idir,idir1,idir2) MAP(to:atom_dprojs,dprojs_r,dprojs_i,kpg) &
    1437              :           !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1438              : #endif
    1439         2904 :           do ilmn=lmn_beg,nlmn
    1440        19272 :             do idir=1,6
    1441     15805720 :               do ipw=1,npw
    1442     15786624 :                 idir1=alpha(idir);idir2=beta(idir)
    1443              :                 dprojs_r(1, ipw, shift_grad+(ilmn-lmn_beg)*ngrads+idir) = &
    1444              :                 &     -half*(atom_dprojs(1, ipw, idir1, ilmn)*kpg(ipw,idir2) &
    1445     15786624 :                 &     +atom_dprojs(1, ipw, idir2, ilmn)*kpg(ipw,idir1))
    1446              : 
    1447              :                 dprojs_i(1, ipw, shift_grad+(ilmn-lmn_beg)*ngrads+idir) = &
    1448              :                 &     -half*(atom_dprojs(2, ipw, idir1, ilmn)*kpg(ipw,idir2) &
    1449     15802992 :                 &     +atom_dprojs(2, ipw, idir2, ilmn)*kpg(ipw,idir1))
    1450              :               end do
    1451              :             end do
    1452              :           end do
    1453              :         end if
    1454              :       end if
    1455              : 
    1456              : 
    1457         1296 :       if(signs==1 .and. (choice==2 .or. choice==23 .or. choice==4 .or. choice==54 .or. choice==6)) then
    1458          648 :         igrad=0; if(choice==23 .or. choice==6) igrad=6
    1459          648 :         if(istwf_k <= 1) then
    1460              : #ifdef HAVE_OPENMP_OFFLOAD
    1461              :           !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1462              :           !$OMP& PRIVATE(ilmn,ipw,idir) MAP(to:projs,dprojs,kpg) &
    1463              :           !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1464              : #endif
    1465         7088 :           do ilmn=lmn_beg,nlmn
    1466        26936 :             do idir=1,3
    1467     43959688 :               do ipw=1,npw
    1468              :                 dprojs(1, ipw, shift_grad+(ilmn-lmn_beg)*ngrads+igrad+idir) = &
    1469     43933224 :                 &     +projs(2, ipw, shift+ilmn-lmn_beg+1)*kpg(ipw,idir)*two_pi
    1470              :                 dprojs(2, ipw, shift_grad+(ilmn-lmn_beg)*ngrads+igrad+idir) = &
    1471     43953072 :                 &     -projs(1, ipw, shift+ilmn-lmn_beg+1)*kpg(ipw,idir)*two_pi
    1472              :               end do
    1473              :             end do
    1474              :           end do
    1475              :         else ! istwf_k>1
    1476              : #ifdef HAVE_OPENMP_OFFLOAD
    1477              :           !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1478              :           !$OMP& PRIVATE(ilmn,ipw,idir) MAP(to:projs_r,projs_i,dprojs_r,dprojs_i,kpg) &
    1479              :           !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1480              : #endif
    1481         2904 :           do ilmn=lmn_beg,nlmn
    1482        11088 :             do idir=1,3
    1483      7904224 :               do ipw=1,npw
    1484              :                 dprojs_r(1, ipw, shift_grad+(ilmn-lmn_beg)*ngrads+igrad+idir) = &
    1485      7893312 :                 &     +projs_i(1, ipw, shift+ilmn-lmn_beg+1)*kpg(ipw,idir)*two_pi
    1486              :                 dprojs_i(1, ipw, shift_grad+(ilmn-lmn_beg)*ngrads+igrad+idir) = &
    1487      7901496 :                 &     -projs_r(1, ipw, shift+ilmn-lmn_beg+1)*kpg(ipw,idir)*two_pi
    1488              :               end do
    1489              :             end do
    1490              :           end do
    1491              :         end if
    1492              :       end if
    1493              : 
    1494         1296 :       if(signs==1 .and. (choice==5 .or. choice==51 .or. choice==54 .or. choice==55)) then
    1495            0 :         igrad=0; if(choice==54) igrad=3; if(choice==55) igrad=6
    1496              : #ifdef HAVE_OPENMP_OFFLOAD
    1497              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1498              :         !$OMP& PRIVATE(ilmn,ipw,idir) MAP(to:atom_dprojs,dprojs) &
    1499              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1500              : #endif
    1501            0 :         do ilmn=lmn_beg,nlmn
    1502            0 :           do idir=1,3
    1503            0 :             do ipw=1,npw
    1504              :               dprojs(1, ipw, shift_grad+(ilmn-lmn_beg)*ngrads+igrad+idir) = &
    1505            0 :               &     +atom_dprojs(1, ipw, idir, ilmn)
    1506              :               dprojs(2, ipw, shift_grad+(ilmn-lmn_beg)*ngrads+igrad+idir) = &
    1507            0 :               &     +atom_dprojs(2, ipw, idir, ilmn)
    1508              :             end do
    1509              :           end do
    1510              :         end do
    1511              :       end if
    1512              : 
    1513         1296 :       if(signs==2 .and. (choice==2)) then
    1514              : #ifdef HAVE_OPENMP_OFFLOAD
    1515              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
    1516              :         !$OMP& PRIVATE(ilmn,ipw) MAP(to:projs,dprojs,kpg) &
    1517              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1518              : #endif
    1519            0 :         do ilmn=lmn_beg,nlmn
    1520            0 :           do ipw=1,npw
    1521              :             dprojs(1, ipw, shift_grad+ilmn) = &
    1522            0 :             &      projs(2, ipw, shift+ilmn-lmn_beg+1)*kpg(ipw,idir_pert)*two_pi
    1523              :             dprojs(2, ipw, shift_grad+ilmn) = &
    1524            0 :             &     -projs(1, ipw, shift+ilmn-lmn_beg+1)*kpg(ipw,idir_pert)*two_pi
    1525              :           end do
    1526              :         end do
    1527              :       end if
    1528              : 
    1529              : 
    1530         1296 :       if(signs==2 .and. (choice==3)) then
    1531              : #ifdef HAVE_OPENMP_OFFLOAD
    1532              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
    1533              :         !$OMP& PRIVATE(ilmn,ipw) MAP(to:atom_dprojs,dprojs) &
    1534              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1535              : #endif
    1536            0 :         do ilmn=lmn_beg,nlmn
    1537            0 :           do ipw=1,npw
    1538              :             dprojs(1, ipw, shift_grad+ilmn) = &
    1539            0 :             &     -atom_dprojs(1, ipw, 1, ilmn)
    1540              :             dprojs(2, ipw, shift_grad+ilmn) = &
    1541            0 :             &     -atom_dprojs(2, ipw, 1, ilmn)
    1542              :           end do
    1543              :         end do
    1544              :       end if
    1545              : 
    1546              : 
    1547         1296 :       if(signs==2 .and. (choice==5 .or. choice==51)) then
    1548              : #ifdef HAVE_OPENMP_OFFLOAD
    1549              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
    1550              :         !$OMP& PRIVATE(ilmn,ipw) MAP(to:atom_dprojs,dprojs) &
    1551              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1552              : #endif
    1553            0 :         do ilmn=lmn_beg,nlmn
    1554            0 :           do ipw=1,npw
    1555              :             dprojs(1, ipw, shift_grad+ilmn) = &
    1556            0 :             &     +atom_dprojs(1, ipw, 1, ilmn)
    1557              :             dprojs(2, ipw, shift_grad+ilmn) = &
    1558            0 :             &     +atom_dprojs(2, ipw, 1, ilmn)
    1559              :           end do
    1560              :         end do
    1561              :       end if
    1562              : 
    1563              : 
    1564              : 
    1565              :       ! Handling d2projs
    1566              : 
    1567         1296 :       if(signs==1 .and. choice==4) then
    1568              : #ifdef HAVE_OPENMP_OFFLOAD
    1569              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) &
    1570              :         !$OMP& PRIVATE(idir,ilmn,ipw) MAP(to:projs,d2projs,kpg) &
    1571              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1572              : #endif
    1573            0 :         do ilmn=lmn_beg,nlmn
    1574            0 :           do idir=1,6
    1575            0 :             do ipw=1,npw
    1576              :               d2projs(1, ipw, shift_grad2+(ilmn-lmn_beg)*ngrads2+idir) = &
    1577            0 :               &     -projs(1, ipw, shift+ilmn-lmn_beg+1)*kpg(ipw,idir+3)*two_pi2
    1578              :               d2projs(2, ipw, shift_grad2+(ilmn-lmn_beg)*ngrads2+idir) = &
    1579            0 :               &     -projs(2, ipw, shift+ilmn-lmn_beg+1)*kpg(ipw,idir+3)*two_pi2
    1580              :             end do
    1581              :           end do
    1582              :         end do
    1583              :       end if
    1584              : 
    1585         1296 :       if(signs==1 .and. choice==54) then
    1586              : #ifdef HAVE_OPENMP_OFFLOAD
    1587              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(4) &
    1588              :         !$OMP& PRIVATE(idir1,idir2,ilmn,ipw) MAP(to:atom_d2projs,d2projs,kpg) &
    1589              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1590              : #endif
    1591            0 :         do ilmn=lmn_beg,nlmn
    1592            0 :           do idir1=1,3
    1593            0 :             do idir2=1,3
    1594            0 :               do ipw=1,npw
    1595              :                 d2projs(1, ipw, shift_grad2+(ilmn-lmn_beg)*ngrads2+(idir1-1)*3+idir2) = &
    1596            0 :                 &     -atom_d2projs(2, ipw, idir2, ilmn)*kpg(ipw,idir1)*two_pi
    1597              :                 d2projs(2, ipw, shift_grad2+(ilmn-lmn_beg)*ngrads2+(idir1-1)*3+idir2) = &
    1598            0 :                 &     +atom_d2projs(1, ipw, idir2, ilmn)*kpg(ipw,idir1)*two_pi
    1599              :               end do
    1600              :             end do
    1601              :           end do
    1602              :         end do
    1603              :       end if
    1604              : 
    1605         1296 :       if(signs==1 .and. choice==55) then
    1606              : #ifdef HAVE_OPENMP_OFFLOAD
    1607              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(4) &
    1608              :         !$OMP& PRIVATE(idir1,idir2,ilmn,ipw) MAP(to:atom_d2projs,d2projs,kpg) &
    1609              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1610              : #endif
    1611            0 :         do ilmn=lmn_beg,nlmn
    1612            0 :           do idir1=1,6
    1613            0 :             do idir2=1,3
    1614            0 :               do ipw=1,npw
    1615              :                 d2projs(1, ipw, shift_grad2+(ilmn-lmn_beg)*ngrads2+(idir1-1)*3+idir2) = &
    1616            0 :                 &     +atom_d2projs(1, ipw, idir1, ilmn)*kpg(ipw,idir2)
    1617              :                 d2projs(2, ipw, shift_grad2+(ilmn-lmn_beg)*ngrads2+(idir1-1)*3+idir2) = &
    1618            0 :                 &     +atom_d2projs(2, ipw, idir1, ilmn)*kpg(ipw,idir2)
    1619              :               end do
    1620              :             end do
    1621              :           end do
    1622              :         end do
    1623              :       end if
    1624              : 
    1625         1296 :       if(signs==1 .and. choice==6) then
    1626              : #ifdef HAVE_OPENMP_OFFLOAD
    1627              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(4) &
    1628              :         !$OMP& PRIVATE(idir1,idir2,jdir1,jdir2,kdir1,kdir2,ldir1,ldir2,ldir3,ldir4,ilmn,ipw) &
    1629              :         !$OMP& MAP(to:atom_d2projs,d2projs,kpg) &
    1630              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1631              : #endif
    1632            0 :         do ilmn=lmn_beg,nlmn
    1633            0 :           do idir1=1,6
    1634            0 :             do idir2=1,6
    1635            0 :               do ipw=1,npw
    1636            0 :                 jdir1=alpha(idir1);jdir2=beta(idir1)
    1637            0 :                 kdir1=alpha(idir2);kdir2=beta(idir2)
    1638            0 :                 ldir1=gamma(jdir1,kdir1)
    1639            0 :                 ldir2=gamma(jdir2,kdir1)
    1640            0 :                 ldir3=gamma(jdir1,kdir2)
    1641            0 :                 ldir4=gamma(jdir2,kdir2)
    1642              :                 d2projs(1, ipw, shift_grad2+(ilmn-lmn_beg)*ngrads2+(idir1-1)*6+idir2) = &
    1643              :                 &     -atom_d2projs(1, ipw, 4+ldir1, ilmn)*kpg(ipw,jdir2)*kpg(ipw,kdir2)*quarter &
    1644              :                 &     -atom_d2projs(1, ipw, 4+ldir2, ilmn)*kpg(ipw,jdir1)*kpg(ipw,kdir2)*quarter &
    1645              :                 &     -atom_d2projs(1, ipw, 4+ldir3, ilmn)*kpg(ipw,jdir2)*kpg(ipw,kdir1)*quarter &
    1646            0 :                 &     -atom_d2projs(1, ipw, 4+ldir4, ilmn)*kpg(ipw,jdir1)*kpg(ipw,kdir1)*quarter
    1647              :                 d2projs(2, ipw, shift_grad2+(ilmn-lmn_beg)*ngrads2+(idir1-1)*6+idir2) = &
    1648              :                 &     -atom_d2projs(2, ipw, 4+ldir1, ilmn)*kpg(ipw,jdir2)*kpg(ipw,kdir2)*quarter &
    1649              :                 &     -atom_d2projs(2, ipw, 4+ldir2, ilmn)*kpg(ipw,jdir1)*kpg(ipw,kdir2)*quarter &
    1650              :                 &     -atom_d2projs(2, ipw, 4+ldir3, ilmn)*kpg(ipw,jdir2)*kpg(ipw,kdir1)*quarter &
    1651            0 :                 &     -atom_d2projs(2, ipw, 4+ldir4, ilmn)*kpg(ipw,jdir1)*kpg(ipw,kdir1)*quarter
    1652              :               end do
    1653              :             end do
    1654              :           end do
    1655              :         end do
    1656            0 :         igrad=36
    1657              : #ifdef HAVE_OPENMP_OFFLOAD
    1658              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(4) &
    1659              :         !$OMP& PRIVATE(idir1,idir2,jdir1,jdir2,ilmn,ipw) &
    1660              :         !$OMP& MAP(to:atom_d2projs,d2projs,kpg) &
    1661              :         !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
    1662              : #endif
    1663            0 :         do ilmn=lmn_beg,nlmn
    1664            0 :           do idir1=1,6 !mub
    1665            0 :             do idir2=1,3 !mua
    1666            0 :               do ipw=1,npw
    1667            0 :                 jdir1=alpha(idir1);jdir2=beta(idir1)
    1668              :                 d2projs(1, ipw, shift_grad2+(ilmn-lmn_beg)*ngrads2+igrad+(idir1-1)*3+idir2) = &
    1669              :                 &     +kpg(ipw,idir2)*(atom_d2projs(2,ipw,1+jdir1,ilmn)*kpg(ipw,jdir2)*pi &
    1670            0 :                 &     +                atom_d2projs(2,ipw,1+jdir2,ilmn)*kpg(ipw,jdir1)*pi)
    1671              : 
    1672              :                 d2projs(2, ipw, shift_grad2+(ilmn-lmn_beg)*ngrads2+igrad+(idir1-1)*3+idir2) = &
    1673              :                 &     -kpg(ipw,idir2)*(atom_d2projs(1,ipw,1+jdir1,ilmn)*kpg(ipw,jdir2)*pi &
    1674            0 :                 &     +                atom_d2projs(1,ipw,1+jdir2,ilmn)*kpg(ipw,jdir1)*pi)
    1675              :               end do
    1676              :             end do
    1677              :           end do
    1678              :         end do
    1679              :       end if
    1680              : 
    1681         1296 :       iaph3d = iaph3d + 1
    1682         1296 :       shift_grad2 = shift_grad2 + ngrads2*(nlmn-lmn_beg+1)
    1683         1296 :       shift_grad  = shift_grad  + ngrads*(nlmn-lmn_beg+1)
    1684              : 
    1685         2008 :       if(gemm_nonlop_block_size > 1) then
    1686            0 :         shift = shift + nlmn - (lmn_beg-1)
    1687            0 :         shift_do = shift_do + nlmn
    1688            0 :         if(shift_do >= iend - 1) exit
    1689              :       else
    1690         1296 :         shift = shift + nlmn
    1691              :       end if
    1692              : 
    1693              :     end do
    1694         1136 :     if(gemm_nonlop_block_size > 1 .and. shift_do >= iend - 1) exit
    1695              :   end do
    1696              : 
    1697              : #ifdef HAVE_OPENMP_OFFLOAD
    1698              :   !!$OMP TARGET EXIT DATA MAP(delete:kpg) IF(gpu_option==ABI_GPU_OPENMP)
    1699              :   !$OMP TARGET EXIT DATA MAP(delete:ffnl) IF(gpu_option==ABI_GPU_OPENMP .and. map_ffnl)
    1700              :   !$OMP TARGET EXIT DATA MAP(delete:ph3d) IF(gpu_option==ABI_GPU_OPENMP .and. map_ph3d)
    1701              : #endif
    1702              : 
    1703          424 :  end subroutine prep_dprojectors
    1704              : !!***
    1705              : 
    1706            0 : end module m_gemm_nonlop_projectors
    1707              : !!***
        

Generated by: LCOV version 2.3-1