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.0 % 467 299
Test Date: 2026-11-06 01:31:13 Functions: 83.3 % 12 10
Branches: 50.0 % 814 407

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

Generated by: LCOV version 2.3-1