LCOV - code coverage report
Current view: top level - src/66_nonlocal - m_gemm_nonlop.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 44.3 % 560 248
Test Date: 2026-11-10 16:57:26 Functions: 33.3 % 3 1
Branches: 26.5 % 1560 413

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_gemm_nonlop
       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,MS)
      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
      35                 :             : 
      36                 :             :  use defs_basis
      37                 :             :  use m_errors
      38                 :             :  use m_abicore
      39                 :             :  use m_xmpi
      40                 :             :  use m_xomp
      41                 :             :  use m_gputk
      42                 :             :  use m_abi_linalg
      43                 :             :  use m_gemm_nonlop_projectors
      44                 :             : 
      45                 :             :  use defs_abitypes, only : MPI_type
      46                 :             :  use m_opernlc_ylm, only : opernlc_ylm
      47                 :             :  use m_opernlc_ylm_allwf, only : opernlc_ylm_allwf
      48                 :             :  use m_opernla_gemm, only : opernla_gemm
      49                 :             :  use m_opernlb_gemm, only : opernlb_gemm
      50                 :             :  use m_opernld_ylm_allwf, only : opernld_ylm_allwf
      51                 :             :  use m_opernld_ylm, only : opernld_ylm
      52                 :             :  use m_pawcprj, only : pawcprj_type
      53                 :             :  use m_geometry, only : strconv
      54                 :             :  use m_kg, only : mkkpg
      55                 :             :  use m_hamiltonian, only : KPRIME_H_K, K_H_KPRIME, K_H_K, KPRIME_H_KPRIME
      56                 :             : 
      57                 :             : #if defined(HAVE_GPU)
      58                 :             :  use m_gpu_toolbox
      59                 :             : #endif
      60                 :             : 
      61                 :             : #ifdef HAVE_FC_ISO_C_BINDING
      62                 :             :  use, intrinsic :: iso_c_binding, only : c_int32_t, c_int64_t, c_float, c_double, c_size_t, c_loc, c_ptr
      63                 :             : #endif
      64                 :             : 
      65                 :             : 
      66                 :             :  implicit none
      67                 :             : 
      68                 :             :  private
      69                 :             : 
      70                 :             :  public :: gemm_nonlop
      71                 :             : 
      72                 :             :  ! Those routines are here to assess memory requirements
      73                 :             :  public :: gemm_nonlop_ompgpu_work_mem
      74                 :             :  public :: gemm_nonlop_ompgpu_static_mem
      75                 :             : !!***
      76                 :             : 
      77                 :             : !----------------------------------------------------------------------
      78                 :             : 
      79                 :             : 
      80                 :             : contains
      81                 :             : 
      82         [ #  # ]:           0 :  function gemm_nonlop_ompgpu_work_mem(istwfk, ndat, ngrads, npw, indlmn, nattyp, ntypat, lmnmax, signs, wfoptalg) result(req_mem)
      83                 :             : 
      84                 :             :    integer, intent(in) :: istwfk, ndat, ngrads, npw, ntypat, lmnmax, signs, wfoptalg
      85                 :             :    integer, intent(in) :: indlmn(:,:,:), nattyp(ntypat)
      86                 :             : 
      87                 :             :    integer :: nprojs, cplex, itypat
      88                 :             :    real(dp) :: req_mem
      89                 :             : 
      90                 :             : ! *************************************************************************
      91                 :             : 
      92         [ #  # ]:           0 :    cplex=2;if (istwfk>1) cplex=1
      93                 :           0 :    nprojs=0
      94         [ #  # ]:           0 :    do itypat=1,ntypat
      95   [ #  #  #  # ]:           0 :      nprojs = nprojs + count(indlmn(3,:,itypat)>0)*nattyp(itypat)
      96                 :             :    end do
      97                 :             : 
      98                 :           0 :    req_mem = 0
      99                 :             : 
     100         [ #  # ]:           0 :    if(cplex == 1) then
     101                 :           0 :      req_mem = req_mem + dp * int(npw, c_size_t) * ndat ! temp_realvec_r
     102                 :           0 :      req_mem = req_mem + dp * int(npw, c_size_t) * ndat ! temp_realvec_i
     103                 :             :    end if
     104                 :             : 
     105                 :           0 :    req_mem = req_mem + dp * lmnmax * (lmnmax+1)/2 * ntypat  ! sij_typ
     106                 :             : 
     107                 :           0 :    req_mem = req_mem + dp * cplex * int(nprojs, c_size_t) * int(ndat, c_size_t)  ! projections
     108                 :           0 :    req_mem = req_mem + dp * cplex * int(nprojs, c_size_t) * int(ndat, c_size_t)  ! s_projections
     109                 :           0 :    req_mem = req_mem + dp * cplex * int(nprojs, c_size_t) * int(ndat, c_size_t)  ! vnl_projections
     110                 :             : 
     111                 :             :    ! Not in a place where vectin, vectout, svectout, enlout are allocated
     112         [ #  # ]:           0 :    if(wfoptalg<0) then
     113                 :           0 :      req_mem = req_mem + dp * cplex * int(npw, c_size_t) * int(ndat, c_size_t)  ! vectin
     114         [ #  # ]:           0 :      if(signs==2) then
     115                 :           0 :        req_mem = req_mem + dp * cplex * int(npw, c_size_t) * int(ndat, c_size_t)  ! vectout
     116                 :           0 :        req_mem = req_mem + dp * cplex * int(npw, c_size_t) * int(ndat, c_size_t)  ! svectout
     117                 :             :      end if
     118         [ #  # ]:           0 :      if(signs==1) then
     119                 :           0 :        req_mem = req_mem + dp * cplex * nprojs * int(ndat, c_size_t)  ! enlout (overestimate)
     120                 :             :      end if
     121                 :             :    end if
     122                 :             : 
     123         [ #  # ]:           0 :    if(ngrads>0) then
     124                 :           0 :      req_mem = req_mem + dp * cplex * ngrads * int(nprojs, c_size_t) * int(ndat, c_size_t)  ! dprojections
     125         [ #  # ]:           0 :      if(signs==2) then
     126                 :           0 :        req_mem = req_mem + dp * cplex * ngrads * int(nprojs, c_size_t) * int(ndat, c_size_t)  ! s_dprojections
     127                 :           0 :        req_mem = req_mem + dp * cplex * ngrads * int(nprojs, c_size_t) * int(ndat, c_size_t)  ! vnl_dprojections
     128                 :             :      end if
     129                 :             :    end if
     130                 :             : 
     131                 :           0 :  end function gemm_nonlop_ompgpu_work_mem
     132                 :             : 
     133                 :             : !----------------------------------------------------------------------
     134                 :             : 
     135         [ #  # ]:           0 :  function gemm_nonlop_ompgpu_static_mem(npw, indlmn, nattyp, ntypat, mpi_block_size, ngrads, use_distrib) result(req_mem)
     136                 :             : 
     137                 :             :    integer, intent(in) :: npw, ntypat, mpi_block_size, ngrads
     138                 :             :    integer, intent(in) :: indlmn(:,:,:), nattyp(ntypat)
     139                 :             :    logical, intent(in) :: use_distrib
     140                 :             : 
     141                 :             :    integer :: nprojs, nprojs_last_blk, itypat
     142                 :             :    integer(kind=c_size_t) :: req_mem
     143                 :             : 
     144                 :             : ! *************************************************************************
     145                 :             : 
     146                 :           0 :    nprojs = 0
     147         [ #  # ]:           0 :    do itypat=1,ntypat
     148   [ #  #  #  # ]:           0 :      nprojs = nprojs + count(indlmn(3,:,itypat)>0)*nattyp(itypat)
     149                 :             :    end do
     150                 :           0 :    nprojs_last_blk = nprojs / mpi_block_size + modulo(nprojs,mpi_block_size)
     151                 :             : 
     152                 :           0 :    req_mem = 0
     153                 :             : 
     154   [ #  #  #  # ]:           0 :    if(mpi_block_size>1 .and. use_distrib) then
     155                 :           0 :      req_mem = req_mem + dp * 2 * int(npw, c_size_t) * int(nprojs_last_blk, c_size_t)          !projs_recv
     156                 :             : #ifdef HAVE_GPU_MPI
     157                 :             :      if(ngrads==0) then
     158                 :             :        ! Add a suspected internal buffer for GPU-aware MPI (no derivatives)
     159                 :             :        req_mem = req_mem + dp * 2 * int(npw, c_size_t) * int(nprojs_last_blk, c_size_t)          !projs_recv
     160                 :             :      end if
     161                 :             : #endif
     162                 :             :    end if
     163                 :             :    ! projs or projs_r + projs_i
     164                 :           0 :    req_mem = req_mem + 2 * dp * int(npw, c_size_t) * int(nprojs_last_blk, c_size_t)
     165         [ #  # ]:           0 :    if(ngrads>0) then
     166                 :             :      ! dprojs or dprojs_r + dprojs_i
     167                 :           0 :      req_mem = req_mem + 2 * dp * int(npw, c_size_t) * int(ngrads, c_size_t) * int(nprojs_last_blk, c_size_t)
     168   [ #  #  #  # ]:           0 :      if(mpi_block_size>1 .and. use_distrib) then
     169                 :           0 :        req_mem = req_mem + dp * 2 * int(npw, c_size_t) * int(ngrads, c_size_t)*int(nprojs_last_blk, c_size_t)   !dprojs_recv
     170                 :             : #ifdef HAVE_GPU_MPI
     171                 :             :        ! Add a suspected internal buffer for GPU-aware MPI (with derivatives)
     172                 :             :        req_mem = req_mem + dp * 2 * int(npw, c_size_t) * int(ngrads, c_size_t)*int(nprojs_last_blk, c_size_t)   !dprojs_recv
     173                 :             : #endif
     174                 :             :      end if
     175                 :             :    end if
     176                 :             : 
     177                 :           0 :  end function gemm_nonlop_ompgpu_static_mem
     178                 :             : 
     179                 :             : !----------------------------------------------------------------------
     180                 :             : 
     181                 :             : !!****f* m_gemm_nonlop/gemm_nonlop
     182                 :             : !! NAME
     183                 :             : !! gemm_nonlop
     184                 :             : !!
     185                 :             : !! FUNCTION
     186                 :             : !! Replacement of nonlop. same prototype as nonlop although not all options are implemented.
     187                 :             : !!
     188                 :             : !! INPUTS
     189                 :             : !! [gpu_option] = GPU implementation to use, i.e. cuda, openMP, ... (0=not using GPU)
     190                 :             : !!
     191                 :             : !! SOURCE
     192         [ -  + ]:       14154 :  subroutine gemm_nonlop(atindx1,choice,cpopt,cprjin,dimenl1,dimenl2,dimekbq,dimffnlin,dimffnlout,&
     193                 :       14154 : &                 enl,enl_ndat,enlout,ffnlin,ffnlout,gmet,gprimd,idir,indlmn,istwf_k,&
     194                 :       28308 : &                 kgin,kgout,kpgin,kpgout,kptin,kptout,lambda,lmnmax,matblk,mgfft,&
     195                 :       14154 : &                 mpi_enreg,natom,nattyp,ndat,ngfft,nkpgin,nkpgout,nloalg,&
     196                 :             : &                 nnlout,npwin,npwout,nspinor,nspinortot,ntypat,only_SO,paw_opt,&
     197                 :       28308 : &                 ph3din,ph3dout,signs,sij,svectout,&
     198   [ -  +  -  + ]:       14154 : &                 tim_nonlop,ucvol,useylm,vectin,vectout,&
     199                 :       14154 : &                 atom_proj_shift,select_k,iatom_only,typat,usepaw,&
     200   [ +  +  +  - ]:       14154 : &                 vectproj,gpu_option)
     201                 :             : 
     202                 :             :   !Arguments ------------------------------------
     203                 :             :   !scalars
     204                 :             :   integer,intent(in) :: choice,cpopt,dimenl1,dimenl2,dimekbq,dimffnlin,dimffnlout,idir
     205                 :             :   integer,intent(in) :: istwf_k,lmnmax,matblk,mgfft,natom,ndat,nkpgin
     206                 :             :   integer,intent(in) :: nkpgout,nnlout,npwin,npwout,nspinor,nspinortot,ntypat,only_SO
     207                 :             :   integer,intent(in) :: paw_opt,signs,tim_nonlop,useylm,atom_proj_shift,select_k,iatom_only,usepaw
     208                 :             :   integer,optional,intent(in) :: gpu_option
     209                 :             :   real(dp),intent(in) :: lambda(ndat),ucvol
     210                 :             :   type(MPI_type),intent(in) :: mpi_enreg
     211                 :             :   !arrays
     212                 :             :   integer,intent(in),target :: atindx1(natom),indlmn(6,lmnmax,ntypat),kgin(3,npwin)
     213                 :             :   integer,intent(in),target :: kgout(3,npwout),nattyp(ntypat),ngfft(18),nloalg(3),typat(natom)
     214                 :             :   real(dp),intent(in),contiguous, target :: enl(:,:,:,:),enl_ndat(:,:,:,:,:)
     215                 :             :   real(dp),intent(in),target :: ffnlin(npwin,dimffnlin,lmnmax,ntypat)
     216                 :             :   real(dp),intent(in),target :: ffnlout(npwout,dimffnlout,lmnmax,ntypat),gmet(3,3)
     217                 :             :   real(dp),intent(in) :: gprimd(3,3),kptin(3),kptout(3)
     218                 :             :   real(dp),intent(in),target :: kpgin(npwin,nkpgin*useylm),kpgout(npwout,nkpgout*useylm)
     219                 :             :   real(dp),intent(in),target :: sij(dimenl1,ntypat*((paw_opt+1)/3))
     220                 :             :   real(dp),intent(inout),target :: ph3din(2,npwin,matblk),ph3dout(2,npwout,matblk)
     221                 :             :   real(dp),intent(inout),target :: vectin(2,npwin*nspinor*ndat)
     222                 :             :   real(dp),intent(inout) :: enlout(nnlout*ndat)
     223                 :             :   real(dp),intent(out),  target :: svectout(:,:)
     224                 :             :   real(dp),intent(inout),target :: vectout(:,:)
     225                 :             :   real(dp),intent(inout),optional, contiguous, target :: vectproj(:,:,:)
     226                 :             :   type(pawcprj_type),intent(inout) :: cprjin(:,:)
     227                 :             : 
     228                 :             :   ! locals
     229                 :             :   integer :: ii, idat, igrad, nprojs, ngrads, ngrads2, shift, iatom, nlmn, ierr, ibeg, iend, ikin, ikout
     230                 :             :   integer :: cplex, cplex_enl, cplex_fac
     231                 :             :   integer :: nnlout_test
     232                 :             :   integer :: iatm, ndgxdt, ndgxdtfac, nd2gxdt, nd2gxdtfac, optder, itypat, ilmn
     233                 :       14154 :   integer,allocatable :: cplex_dgxdt(:), cplex_d2gxdt(:)
     234                 :             :   logical :: local_vectproj,use_enl_ndat
     235                 :             :   real(dp) :: d2gxdt_dum_in(1,1,1,1,1), d2gxdt_dum_out(1,1,1,1,1),d2gxdt_dum_out2(1,1,1,1,1)
     236                 :       14154 :   real(dp), allocatable :: sij_typ(:,:)
     237                 :       14154 :   real(dp), contiguous, pointer :: projections(:,:,:)
     238                 :       14154 :   real(dp), allocatable :: s_projections(:,:,:), vnl_projections(:,:,:)
     239                 :       14154 :   real(dp), allocatable :: dprojections(:,:,:), temp_realvec_r(:), temp_realvec_i(:)
     240                 :       14154 :   real(dp), allocatable, target :: s_dprojections(:,:,:), vnl_dprojections(:,:,:)
     241                 :       14154 :   real(dp), allocatable, target :: d2projections(:,:,:)
     242                 :       14154 :   real(dp), allocatable :: enlk(:),fnlk(:,:),ddkk(:,:),strnlk(:,:),gmet2(:,:)
     243                 :       14154 :   real(dp), allocatable :: work1(:),work2(:),work3(:,:),work4(:,:),work5(:,:,:),work6(:,:,:),work7(:,:,:)
     244                 :             :   integer :: idbeg,idend,idfbeg,idfend,dshift,id2beg,id2end,d2shift,dfshift,enlout_shift,ndat_enl
     245                 :             :   real(dp) :: work(6)
     246                 :             :   integer :: ndgxdt_stored,ishift
     247                 :             :   integer :: mu0,ic,nu,mu,jc,mua,mub,nua1,nua2,nub1,nub2
     248                 :             :   integer,parameter :: alpha(6)=(/1,2,3,3,3,2/),beta(6)=(/1,2,3,2,1,1/)
     249                 :             :   integer,parameter :: gamma(3,3)=reshape((/1,6,5,6,2,4,5,4,3/),(/3,3/))
     250                 :             :   integer          ::  matblk_,natom_,ntypat_,ispden,dimenl2_,ia_beg,ia_end,dimsij,nkpgin_,nkpgout_
     251                 :       14154 :   integer, contiguous, pointer :: atindx1_(:),indlmn_(:,:,:),nattyp_(:)
     252                 :       14154 :   real(dp),pointer :: ffnlin_(:,:,:,:),ffnlout_(:,:,:,:)
     253                 :       14154 :   real(dp),pointer :: ph3din_(:,:,:),ph3dout_(:,:,:)
     254                 :       14154 :   real(dp), contiguous, pointer :: enl_(:,:,:,:,:)
     255                 :       14154 :   real(dp), contiguous, pointer :: sij_(:,:)
     256                 :       14154 :   real(dp), contiguous, pointer :: kpgin_(:,:),kpgout_(:,:)
     257                 :             :   logical :: nld_on_gpu
     258                 :             : 
     259                 :             :   logical :: transfer_vectin,transfer_vectout,transfer_svectout
     260                 :       14154 :   real(dp), pointer :: vectin_(:,:),vectout_(:,:),svectout_(:,:)
     261                 :             : 
     262                 :             : ! *************************************************************************
     263                 :             : 
     264                 :             :   ! We keep the same interface as nonlop, but we don't use many of those
     265                 :             :   ABI_UNUSED((/gmet/))
     266                 :             :   ABI_UNUSED((/mgfft/))
     267                 :             :   ABI_UNUSED((/nloalg,ngfft,only_SO,tim_nonlop/))
     268                 :             : 
     269                 :             :   ! Check supported options
     270                 :       14154 :   if (.not.gemm_nonlop_use_gemm) then
     271                 :           0 :     ABI_BUG('computation not prepared for gemm_nonlop use!')
     272                 :             :   end if
     273                 :             :   if ( (choice>3.and.choice/=7.and.choice/=5.and.choice/=51.and.signs==2) .or. &
     274   [ -  +  -  -  :       14154 : &      (choice>3.and.choice/=7.and.choice/=23.and.choice/=4.and.choice/=54.and.choice/=55.and.choice/=6.and.signs==1) .or. &
          -  -  -  -  -  
             +  -  -  -  
                      + ]
     275                 :             : &      (useylm/=1) ) then
     276                 :           0 :     ABI_BUG('gemm_nonlop option not supported!')
     277                 :             :   end if
     278         [ +  + ]:       14154 :   if (signs==1) then
     279                 :        2676 :     nnlout_test=0
     280         [ +  + ]:        2676 :     if (choice==1) nnlout_test=1
     281         [ +  + ]:        2676 :     if (choice==2) nnlout_test=3*natom
     282         [ +  + ]:        2676 :     if (choice==3) nnlout_test=6
     283         [ -  + ]:        2676 :     if (choice==23) nnlout_test=6+3*natom
     284         [ -  + ]:        2676 :     if (nnlout<nnlout_test) then
     285                 :           0 :       ABI_BUG('wrong nnlout size!')
     286                 :             :     end if
     287                 :             :   end if
     288                 :             : 
     289                 :       14154 :   transfer_vectin=.false.; transfer_vectout=.false.; transfer_svectout=.false.
     290         [ -  + ]:       14154 :   if(gpu_option==ABI_GPU_OPENMP) then
     291                 :             :     ! Check if provided buffers are already mapped on GPU
     292                 :             :     transfer_vectin=.not. xomp_target_is_present(c_loc(vectin)) &
     293                 :             :         .and. ((cpopt < 2 .and. choice < 2) .or. (cpopt <= 3 .and. choice >= 2) &
     294                 :           0 :         .or. (choice/=7 .and.paw_opt >=3))
     295                 :             :     transfer_vectout=.not. xomp_target_is_present(c_loc(vectout)) &
     296                 :           0 :         .and. (signs==2 .and. (paw_opt == 0 .or. paw_opt == 1 .or. paw_opt == 4))
     297                 :             :     transfer_svectout=.not. xomp_target_is_present(c_loc(svectout)) &
     298                 :           0 :         .and. (signs==2 .and. (paw_opt == 3 .or. paw_opt == 4))
     299                 :             :   end if
     300                 :             : 
     301                 :       14154 :   ikin=1; ikout=1;
     302                 :       14154 :   select case (select_k)
     303                 :             :   case (K_H_K)
     304                 :             :     ikin=1; ikout=1;
     305                 :             :   case (K_H_KPRIME)
     306                 :             :     ikin=2; ikout=1;
     307                 :             :   case (KPRIME_H_K)
     308                 :             :     ikin=1; ikout=2;
     309                 :             :   case (KPRIME_H_KPRIME)
     310         [ +  - ]:       14154 :     ikin=2; ikout=2;
     311                 :             :   end select
     312         [ +  + ]:       14154 :   cplex=2;if (istwf_k>1) cplex=1
     313         [ +  + ]:       14154 :   cplex_enl=1;if (paw_opt>0) cplex_enl=2*dimenl1/(lmnmax*(lmnmax+1)) ! is enl complex?
     314                 :       14154 :   cplex_fac=max(cplex,dimekbq)
     315   [ +  -  -  +  :       14154 :   if ((nspinortot==2.or.cplex_enl==2).and.paw_opt>0.and.choice/=7) cplex_fac=2 ! is vnl_projections complex?
             -  -  -  - ]
     316   [ +  +  +  - ]:       84924 :   use_enl_ndat=.false. ; if (size(enl_ndat)>0) use_enl_ndat=.true.
     317                 :       14154 :   ndat_enl=1; if(use_enl_ndat) ndat_enl=ndat
     318                 :             : 
     319                 :             :   ! Processing one atom : set pointers to atom-specific arrays (for opernlc)
     320         [ -  + ]:       14154 :   if(iatom_only > 0) then
     321                 :           0 :     iatm=atindx1(iatom_only);itypat=typat(iatom_only)
     322                 :           0 :     ia_beg=iatom_only; ia_end=iatom_only
     323                 :           0 :     natom_=1 ; ntypat_=1 ; dimenl2_=1 ; matblk_=1
     324         [ #  # ]:           0 :     ABI_MALLOC(atindx1_,(1))
     325         [ #  # ]:           0 :     ABI_MALLOC(nattyp_,(1))
     326                 :           0 :     atindx1_(1)=1 ; nattyp_(1)=1
     327   [ #  #  #  #  :           0 :     ABI_MALLOC(ph3din_,(2,npwin,1))
          #  #  #  #  #  
                #  #  # ]
     328   [ #  #  #  #  :           0 :     ABI_MALLOC(ph3dout_,(2,npwout,1))
          #  #  #  #  #  
                #  #  # ]
     329   [ #  #  #  #  :           0 :     ph3din_(:,1:npwin,1)=ph3din(:,1:npwin,iatm)
          #  #  #  #  #  
                      # ]
     330   [ #  #  #  #  :           0 :     ph3dout_(:,1:npwout,1)=ph3dout(:,1:npwout,iatm)
          #  #  #  #  #  
                      # ]
     331   [ #  #  #  #  :           0 :     ABI_MALLOC(ffnlin_,(npwin,dimffnlin,lmnmax,1))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     332   [ #  #  #  #  :           0 :     ABI_MALLOC(ffnlout_,(npwout,dimffnlout,lmnmax,1))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     333   [ #  #  #  #  :           0 :     ffnlin_(:,:,:,1)=ffnlin(:,:,:,itypat)
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     334   [ #  #  #  #  :           0 :     ffnlout_(:,:,:,1)=ffnlout(:,:,:,itypat)
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     335   [ #  #  #  #  :           0 :     ABI_MALLOC(indlmn_,(6,lmnmax,1))
          #  #  #  #  #  
                #  #  # ]
     336   [ #  #  #  #  :           0 :     indlmn_(:,:,1)=indlmn(:,:,itypat)
          #  #  #  #  #  
                      # ]
     337   [ #  #  #  # ]:           0 :     if (size(sij)>0) then
     338                 :           0 :       dimsij=size(sij,1)
     339   [ #  #  #  #  :           0 :       ABI_MALLOC(sij_,(dimsij,1))
          #  #  #  #  #  
                #  #  # ]
     340         [ #  # ]:           0 :       if (size(sij,2)==ntypat) then
     341   [ #  #  #  #  :           0 :         sij_(:,1)=sij(:,itypat)
                   #  # ]
     342   [ #  #  #  # ]:           0 :       else if (size(sij)>0) then
     343   [ #  #  #  #  :           0 :         sij_(:,1)=sij(:,1)
                   #  # ]
     344                 :             :       end if
     345                 :             :     end if
     346   [ #  #  #  # ]:           0 :     if (size(enl_ndat)>0) then
     347   [ #  #  #  #  :           0 :       ABI_MALLOC(enl_,(size(enl_ndat,1),1,nspinor**2,ndat,size(enl_ndat,5)))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     348         [ #  # ]:           0 :       do idat=1,ndat
     349         [ #  # ]:           0 :         do ii=1,size(enl_ndat,5)
     350         [ #  # ]:           0 :           do ispden=1,nspinor**2
     351   [ #  #  #  # ]:           0 :             if (dimenl2==natom .and. usepaw==1) then
     352   [ #  #  #  #  :           0 :               enl_(:,1,ispden,idat,ii)=enl_ndat(:,iatom_only,ispden,idat,ii)
                   #  # ]
     353         [ #  # ]:           0 :             else if (dimenl2==ntypat) then
     354   [ #  #  #  #  :           0 :               enl_(:,1,ispden,idat,ii)=enl_ndat(:,itypat,ispden,idat,ii)
                   #  # ]
     355                 :             :             else
     356   [ #  #  #  #  :           0 :               enl_(:,1,ispden,idat,ii)=enl_ndat(:,1,ispden,idat,ii)
                   #  # ]
     357                 :             :             end if
     358                 :             :           end do
     359                 :             :         end do
     360                 :             :       end do
     361   [ #  #  #  # ]:           0 :     else if (size(enl)>0) then
     362   [ #  #  #  #  :           0 :       ABI_MALLOC(enl_,(size(enl,1),1,nspinor**2,size(enl,4),1))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     363         [ #  # ]:           0 :       do ii=1,size(enl,4)
     364         [ #  # ]:           0 :         do ispden=1,nspinor**2
     365   [ #  #  #  # ]:           0 :           if (dimenl2==natom .and. usepaw==1) then
     366   [ #  #  #  #  :           0 :             enl_(:,1,ispden,ii,1)=enl(:,iatom_only,ispden,ii)
                   #  # ]
     367         [ #  # ]:           0 :           else if (dimenl2==ntypat) then
     368   [ #  #  #  #  :           0 :             enl_(:,1,ispden,ii,1)=enl(:,itypat,ispden,ii)
                   #  # ]
     369                 :             :           else
     370   [ #  #  #  #  :           0 :             enl_(:,1,ispden,ii,1)=enl(:,1,ispden,ii)
                   #  # ]
     371                 :             :           end if
     372                 :             :         end do
     373                 :             :       end do
     374                 :             :     else
     375         [ #  # ]:           0 :       ABI_MALLOC(enl_,(0,0,0,0,0))
     376                 :             :     end if
     377                 :             : 
     378                 :             :   ! Usual case : all atoms are processed
     379                 :             :   else
     380                 :       14154 :     natom_  =natom; ntypat_=ntypat
     381                 :       14154 :     ia_beg=1; ia_end=natom
     382                 :       14154 :     dimenl2_=dimenl2   ; matblk_=matblk
     383                 :       14154 :     atindx1_    => atindx1
     384                 :       14154 :     nattyp_     => nattyp
     385                 :       14154 :     ffnlin_     => ffnlin
     386                 :       14154 :     ffnlout_    => ffnlout
     387                 :       14154 :     enl_(1:dimenl1,1:dimenl2,1:nspinortot**2,1:dimekbq,1:1)        => enl(:,:,:,:)
     388         [ -  + ]:       14154 :     if(use_enl_ndat) then
     389                 :           0 :       enl_   => enl_ndat
     390                 :             :     end if
     391                 :       14154 :     sij_        => sij
     392                 :       14154 :     indlmn_     => indlmn
     393                 :       14154 :     ph3din_     => ph3din
     394                 :       14154 :     ph3dout_    => ph3dout
     395                 :             :   end if
     396                 :             : 
     397                 :             :   ! The number of projectors used for computation may vary among
     398                 :             :   ! nonlop calls, from computing on all atoms to a select one for
     399                 :             :   ! some perturbations.
     400                 :             :   ! In such cases, projs arrays must be recomputed
     401                 :       14154 :   nprojs=0
     402         [ +  + ]:       37718 :   do itypat=1,ntypat_
     403   [ +  +  +  + ]:      414430 :     nprojs = nprojs + count(indlmn_(3,:,itypat)>0)*nattyp_(itypat)
     404                 :             :   end do
     405                 :             : 
     406         [ -  + ]:       14154 :   if(nprojs == 0) then
     407                 :             :     ! TODO check if this is correct
     408         [ #  # ]:           0 :     if (iatom_only>0) then
     409         [ #  # ]:           0 :       ABI_FREE(atindx1_)
     410         [ #  # ]:           0 :       ABI_FREE(nattyp_)
     411         [ #  # ]:           0 :       ABI_FREE(ph3din_)
     412         [ #  # ]:           0 :       ABI_FREE(ph3dout_)
     413         [ #  # ]:           0 :       ABI_FREE(ffnlin_)
     414         [ #  # ]:           0 :       ABI_FREE(ffnlout_)
     415         [ #  # ]:           0 :       ABI_FREE(enl_)
     416         [ #  # ]:           0 :       ABI_FREE(indlmn_)
     417   [ #  #  #  # ]:           0 :       if (size(sij) > 1) then
     418         [ #  # ]:           0 :         ABI_FREE(sij_)
     419                 :             :       end if
     420                 :             :     end if
     421         [ #  # ]:           0 :     if(signs == 1) then
     422         [ #  # ]:           0 :       enlout=zero
     423                 :             :       return
     424                 :             :     end if
     425         [ #  # ]:           0 :     if(signs == 2) then
     426         [ #  # ]:           0 :       if(gpu_option==ABI_GPU_DISABLED) then
     427   [ #  #  #  # ]:           0 :         vectout = zero
     428   [ #  #  #  #  :           0 :         if(paw_opt>0) svectout = vectin
          #  #  #  #  #  
                #  #  # ]
     429                 :             :       else if(gpu_option==ABI_GPU_OPENMP) then
     430                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     431                 :             :         if(transfer_vectout) then
     432                 :             :           vectout = zero
     433                 :             :         else
     434                 :             :           call gpu_set_to_zero(vectout, int(2,c_size_t) * npwout * nspinor * ndat)
     435                 :             :         end if
     436                 :             :         if(paw_opt>0) then
     437                 :             :           if(transfer_svectout .and. transfer_vectin) then
     438                 :             :             svectout = vectin
     439                 :             :           else if(transfer_vectin) then
     440                 :             :             svectout = vectin
     441                 :             :             !$OMP TARGET UPDATE TO(svectout)
     442                 :             :           else if(transfer_svectout) then
     443                 :             :             !$OMP TARGET UPDATE FROM(vectin)
     444                 :             :             svectout = vectin
     445                 :             :           else
     446                 :             :             call gpu_copy(svectout, vectin, int(2,c_size_t) * npwin * nspinor * ndat)
     447                 :             :           end if
     448                 :             :         end if
     449                 :             : #endif
     450                 :             :       end if
     451                 :           0 :       return
     452                 :             :     end if
     453                 :             :   end if
     454                 :             : 
     455                 :             :   !Eventually re-compute (k+G) vectors (and related data)
     456                 :       14154 :   nkpgin_=0
     457         [ +  + ]:       14154 :   if (choice==2.or.choice==54) nkpgin_=3
     458         [ +  + ]:       14154 :   if (signs==1) then
     459         [ -  + ]:        2676 :     if (choice==4) nkpgin_=9
     460         [ +  + ]:        2676 :     if (choice==3.or.choice==23.or.choice==6) nkpgin_=3
     461         [ -  + ]:        2676 :     if (choice==55) nkpgin_=3
     462                 :             :   end if
     463         [ +  + ]:       14154 :   if (nkpgin<nkpgin_) then
     464   [ -  +  +  -  :         256 :     ABI_MALLOC(kpgin_,(npwin,nkpgin_))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     465                 :          64 :     call mkkpg(kgin,kpgin_,kptin,nkpgin_,npwin)
     466                 :             :   else
     467                 :       14090 :     nkpgin_ = nkpgin
     468                 :       14090 :     kpgin_  => kpgin
     469                 :             :   end if
     470                 :             : 
     471                 :       14154 :   nkpgout_=0
     472   [ +  +  -  + ]:       14154 :   if ((choice==2.or.choice==3.or.choice==54).and.signs==2) nkpgout_=3
     473         [ -  + ]:       14154 :   if (nkpgout<nkpgout_) then
     474   [ #  #  #  #  :           0 :     ABI_MALLOC(kpgout_,(npwout,nkpgout_))
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     475                 :           0 :     call mkkpg(kgout,kpgout_,kptout,nkpgout_,npwout)
     476                 :             :   else
     477                 :       14154 :     nkpgout_ = nkpgout
     478                 :       14154 :     kpgout_ => kpgout
     479                 :             :   end if
     480                 :             : 
     481                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     482                 :             :   !$OMP TARGET ENTER DATA MAP(to:kpgin_)  if(nkpgin_  > 0 .and. gpu_option==ABI_GPU_OPENMP)
     483                 :             :   !$OMP TARGET ENTER DATA MAP(to:kpgout_) if(nkpgout_ > 0 .and. gpu_option==ABI_GPU_OPENMP)
     484                 :             : 
     485                 :             :   ! Allocate and copy GPU buffers if user doesn't manage them
     486                 :             :   !$OMP TARGET ENTER DATA MAP(to:vectin)      IF(transfer_vectin)
     487                 :             :   !$OMP TARGET ENTER DATA MAP(alloc:vectout)  IF(transfer_vectout)
     488                 :             :   !$OMP TARGET ENTER DATA MAP(alloc:svectout) IF(transfer_svectout)
     489                 :             : 
     490                 :             :   !$OMP TARGET ENTER DATA MAP(to:atindx1,indlmn) IF(gpu_option==ABI_GPU_OPENMP)
     491                 :             :   if(size(enl_)>0) then
     492                 :             :     !$OMP TARGET ENTER DATA MAP(to:enl_) IF(gpu_option==ABI_GPU_OPENMP)
     493                 :             :   end if
     494                 :             : #endif
     495                 :             : 
     496                 :             :   !FIXME These seemingly useless pointers are used in BLAS operations for
     497                 :             :   ! working around a bug in AOMP LLVM misreading mapped device pointers.
     498                 :             :   ! I chose to generalise the workaround to avoid dupplicating each
     499                 :             :   ! BLAS call specifically for handling AOMP LLVM.
     500                 :       14154 :   vectin_   => vectin
     501                 :       14154 :   vectout_  => vectout
     502                 :       14154 :   svectout_ => svectout
     503                 :             : 
     504                 :             :   ! If vectproj is provided, use it for further calculations, use allocated array otherwise
     505                 :       14154 :   local_vectproj=.false.
     506         [ +  + ]:       14154 :   if(PRESENT(vectproj)) then
     507   [ +  +  +  - ]:        4608 :     if(size(vectproj)>1) local_vectproj=.true.
     508                 :             :   end if
     509                 :        1152 :   if (local_vectproj) projections => vectproj
     510                 :             : 
     511                 :             : 
     512   [ +  +  +  + ]:       14154 :   if(signs == 1 .and. choice > 0) then
     513         [ +  + ]:       18568 :     enlout=zero
     514   [ -  +  +  -  :        1560 :     ABI_MALLOC(enlk,(ndat))
          +  -  +  -  -  
                +  -  + ]
     515         [ +  + ]:        2824 :     enlk=zero
     516   [ +  -  -  +  :        2080 :     ABI_MALLOC(fnlk,(3*natom,ndat))
          +  -  -  +  +  
          -  +  -  +  -  
             -  +  -  + ]
     517   [ +  +  +  + ]:       48904 :     fnlk=zero
     518   [ -  +  +  -  :        1560 :     ABI_MALLOC(ddkk,(6,ndat))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     519   [ +  +  +  + ]:       16648 :     ddkk=zero
     520   [ -  +  +  -  :        1040 :     ABI_MALLOC(strnlk,(6,ndat))
             -  +  -  + ]
     521   [ +  +  +  + ]:       16648 :     strnlk=zero
     522                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     523                 :             :     !$OMP TARGET ENTER DATA MAP(to:enlout,enlk,fnlk,ddkk,strnlk) IF(gpu_option==ABI_GPU_OPENMP)
     524                 :             : #endif
     525                 :             :   end if
     526                 :             : 
     527   [ +  +  +  +  :       14154 :   if(paw_opt>=2 .and. choice > 0 .and. choice /= 7) then
                   +  + ]
     528   [ +  -  -  +  :       34424 :     ABI_MALLOC(sij_typ,(lmnmax*(lmnmax+1)/2,ntypat))
          +  -  -  +  +  
          -  +  -  +  -  
             -  +  -  + ]
     529         [ +  - ]:        8606 :     if (cplex_enl==1) then
     530         [ +  + ]:       22910 :       do itypat=1, ntypat_
     531   [ +  +  +  - ]:      242696 :         nlmn=count(indlmn_(3,:,itypat)>0)
     532         [ +  + ]:     2076314 :         do ilmn=1,nlmn*(nlmn+1)/2
     533                 :     2067708 :           sij_typ(ilmn,itypat)=sij_(ilmn,itypat)
     534                 :             :         end do
     535                 :             :       end do
     536                 :             :     else
     537         [ #  # ]:           0 :       do itypat=1, ntypat_
     538   [ #  #  #  # ]:           0 :         nlmn=count(indlmn_(3,:,itypat)>0)
     539         [ #  # ]:           0 :         do ilmn=1,nlmn*(nlmn+1)/2
     540                 :           0 :           sij_typ(ilmn,itypat)=sij_(2*ilmn-1,itypat)
     541                 :             :         end do
     542                 :             :       end do
     543                 :             :     end if
     544                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     545                 :             :     !$OMP TARGET ENTER DATA MAP(to:sij_typ) IF(gpu_option==ABI_GPU_OPENMP)
     546                 :             : #endif
     547                 :             :   else
     548   [ -  +  +  -  :       16644 :     ABI_MALLOC(sij_typ,(1,ntypat)) ! Dummy alloc
          +  -  +  -  -  
                +  -  + ]
     549                 :             :   end if
     550                 :             : 
     551                 :       14154 :   ndgxdt = -1
     552                 :       14154 :   nd2gxdt = -1
     553                 :             : 
     554                 :       14154 :   ndgxdtfac = 0; nd2gxdtfac = 0
     555         [ +  + ]:       14154 :   if (choice==2) then
     556         [ +  - ]:         212 :     if (signs==1) ndgxdt=3
     557         [ -  + ]:         212 :     if (signs==2) ndgxdt=1
     558         [ -  + ]:         212 :     if (signs==2) ndgxdtfac=1
     559                 :             :   end if
     560         [ -  + ]:       14154 :   if (choice==22) then
     561         [ #  # ]:           0 :     if (signs==2) ndgxdtfac=1
     562                 :             :   end if
     563         [ -  + ]:       14154 :   if (choice==23) then
     564         [ #  # ]:           0 :     if (signs==1) ndgxdt=9
     565                 :             :   end if
     566         [ +  + ]:       14154 :   if (choice==3) then
     567         [ +  - ]:         212 :     if (signs==1) ndgxdt=6
     568         [ -  + ]:         212 :     if (signs==2) ndgxdt=1
     569         [ -  + ]:         212 :     if (signs==2) ndgxdtfac=1
     570                 :             :   end if
     571         [ -  + ]:       14154 :   if (choice==4) then
     572         [ #  # ]:           0 :     if(signs==1) ndgxdt=3
     573         [ #  # ]:           0 :     if(signs==1) ndgxdtfac=3
     574         [ #  # ]:           0 :     if(signs==1) nd2gxdt=6
     575                 :             :   end if
     576         [ -  + ]:       14154 :   if (choice==5) then
     577         [ #  # ]:           0 :     if(signs==1) ndgxdt=3
     578         [ #  # ]:           0 :     if(signs==2) ndgxdt=1
     579         [ #  # ]:           0 :     if(signs==2) ndgxdtfac=1
     580                 :             :   end if
     581         [ -  + ]:       14154 :   if (choice==51) then
     582         [ #  # ]:           0 :     if(signs==1) ndgxdt=3
     583         [ #  # ]:           0 :     if(signs==2) ndgxdt=1
     584         [ #  # ]:           0 :     if(signs==2) ndgxdtfac=1
     585                 :             :   end if
     586         [ -  + ]:       14154 :   if (choice==54) then
     587         [ #  # ]:           0 :     if(signs==1) ndgxdt=6
     588         [ #  # ]:           0 :     if(signs==1) ndgxdtfac=6
     589         [ #  # ]:           0 :     if(signs==1) nd2gxdt=9
     590         [ #  # ]:           0 :     if(signs==2) ndgxdt=1
     591         [ #  # ]:           0 :     if(signs==2) nd2gxdt=1
     592         [ #  # ]:           0 :     if(signs==2) ndgxdtfac=1
     593         [ #  # ]:           0 :     if(signs==2) nd2gxdtfac=1
     594                 :             :   end if
     595         [ -  + ]:       14154 :   if (choice==55) then
     596         [ #  # ]:           0 :     if(signs==1) ndgxdt=9
     597         [ #  # ]:           0 :     if(signs==1) ndgxdtfac=9
     598         [ #  # ]:           0 :     if(signs==1) nd2gxdt=18
     599                 :             :   end if
     600         [ -  + ]:       14154 :   if (choice==6) then
     601         [ #  # ]:           0 :     if(signs==1) ndgxdt=9
     602         [ #  # ]:           0 :     if(signs==1) ndgxdtfac=9
     603         [ #  # ]:           0 :     if(signs==1) nd2gxdt=54
     604                 :             :   end if
     605                 :       14154 :   ngrads=0; ngrads2=0
     606         [ +  + ]:       14154 :   if(ndgxdt>0) ngrads=ndgxdt; if(ndgxdt>0) ngrads2=nd2gxdt
     607         [ +  + ]:       14154 :   if(ndgxdt>0) then
     608         [ -  + ]:         424 :     ABI_CHECK(ndgxdtfac<=ndgxdt,"BUG: ndgxdtfac>ndgxdt!")
     609                 :             :   end if
     610         [ -  + ]:       14154 :   optder = 0;if (ndgxdtfac>0) optder = 1
     611         [ -  + ]:       14154 :   if (nd2gxdtfac>0) optder=2
     612   [ +  +  +  -  :       42462 :   ABI_MALLOC(cplex_dgxdt, (ndgxdt))
          +  -  +  +  -  
                +  -  + ]
     613   [ +  -  -  -  :       42462 :   ABI_MALLOC(cplex_d2gxdt,(nd2gxdt))
          +  -  -  +  -  
                +  -  + ]
     614   [ +  +  -  + ]:       16062 :   cplex_dgxdt(:) = 1 ; cplex_d2gxdt(:) = 1
     615                 :             :   ! When istwf_k > 1, gx derivatives can be real or pure imaginary
     616                 :             :   ! cplex_dgxdt(i)  = 1 if dgxdt(1,i,:,:)  is real, 2 if it is pure imaginary
     617                 :             :   ! cplex_d2gxdt(i) = 1 if d2gxdt(1,i,:,:) is real, 2 if it is pure imaginary
     618         [ +  + ]:       14154 :   if(ndgxdt > 0) then
     619   [ -  +  -  - ]:         424 :    if (choice==5.or.choice==51) cplex_dgxdt(:) = 2
     620   [ -  +  -  -  :         424 :    if (choice==54.and.signs==1) cplex_dgxdt(4:6) = 2
                   -  - ]
     621                 :             :    !if (choice==54.and.signs==2) cplex_dgxdt(:)   = 2
     622   [ -  +  -  -  :         424 :    if (choice==55.and.signs==1) cplex_dgxdt(7:9) = 2
                   -  - ]
     623                 :             :   end if
     624         [ -  + ]:       14154 :   if(nd2gxdt > 0) then
     625   [ #  #  #  # ]:           0 :     if (choice==54) cplex_d2gxdt(:) = 2
     626   [ #  #  #  #  :           0 :     if (choice==55.and.signs==1) cplex_d2gxdt(1:18)= 2
                   #  # ]
     627                 :             :   end if
     628                 :             : 
     629                 :             :   ! These will store the non-local factors for vectin, svectout and vectout respectively
     630         [ +  + ]:       14154 :   if(.not. local_vectproj) then
     631   [ -  +  +  -  :       65010 :     ABI_MALLOC(projections,(cplex, nprojs,nspinor*ndat))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  -  +  -  
                      + ]
     632                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     633                 :             :     !$OMP TARGET ENTER DATA MAP(alloc:projections) IF(gpu_option==ABI_GPU_OPENMP)
     634                 :             : #endif
     635                 :             :   end if
     636   [ -  +  +  -  :       70770 :   ABI_MALLOC(s_projections,(cplex, nprojs,nspinor*ndat))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  -  +  -  
                      + ]
     637   [ -  +  +  -  :       70770 :   ABI_MALLOC(vnl_projections,(cplex_fac, nprojs,nspinor*ndat))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  -  +  -  
                      + ]
     638                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     639                 :             :   !$OMP TARGET ENTER DATA MAP(alloc:s_projections,vnl_projections) IF(gpu_option==ABI_GPU_OPENMP)
     640                 :             : #endif
     641                 :             : 
     642         [ +  - ]:       14154 :   if(gpu_option==ABI_GPU_DISABLED) then
     643   [ +  +  +  +  :     8482993 :     if(cpopt < 2) projections = zero
             +  +  +  + ]
     644   [ +  +  +  +  :     8694673 :     s_projections = zero
                   +  + ]
     645   [ +  +  +  +  :     8694673 :     vnl_projections = zero
                   +  + ]
     646         [ #  # ]:           0 :   else if(gpu_option==ABI_GPU_OPENMP) then
     647         [ #  # ]:           0 :     if(cpopt < 2) call gpu_set_to_zero(projections,   int(cplex,c_size_t)*nprojs*ndat*nspinor)
     648                 :           0 :     call gpu_set_to_zero(s_projections,   int(cplex,c_size_t)*nprojs*ndat*nspinor)
     649                 :           0 :     call gpu_set_to_zero(vnl_projections, int(cplex_fac,c_size_t)*nprojs*ndat*nspinor)
     650                 :             :   end if
     651                 :             : 
     652                 :             :   ! Working buffers for storing derivative
     653         [ +  + ]:       14154 :   if (ndgxdt>0) then
     654   [ -  +  +  -  :        2120 :     ABI_MALLOC(dprojections,(cplex, ndgxdt*nprojs,nspinor*ndat))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  -  +  -  
                      + ]
     655                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     656                 :             :     !$OMP TARGET ENTER DATA MAP(alloc:dprojections) IF(gpu_option==ABI_GPU_OPENMP)
     657                 :             : #endif
     658         [ +  - ]:         424 :     if(cpopt < 4) then
     659         [ +  - ]:         424 :       if(gpu_option==ABI_GPU_DISABLED) then
     660   [ +  +  +  +  :     1464640 :         dprojections(:,:,:) = zero
                   +  + ]
     661         [ #  # ]:           0 :       else if(gpu_option==ABI_GPU_OPENMP) then
     662                 :           0 :         call gpu_set_to_zero(dprojections, int(cplex,c_size_t)*ndgxdt*nprojs*ndat*nspinor)
     663                 :             :       end if
     664                 :             :     end if
     665                 :             :   else
     666   [ -  +  +  -  :       41190 :     ABI_MALLOC(dprojections,(1,1,ndat))
          +  -  +  -  -  
                +  -  + ]
     667                 :             :   end if
     668                 :             : 
     669         [ -  + ]:       14154 :   if (ndgxdtfac>0) then
     670   [ #  #  #  #  :           0 :     ABI_MALLOC(s_dprojections,(cplex, ndgxdtfac*nprojs,nspinor*ndat))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     671   [ #  #  #  #  :           0 :     ABI_MALLOC(vnl_dprojections,(cplex_fac, ndgxdtfac*nprojs,nspinor*ndat))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     672                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     673                 :             :     !$OMP TARGET ENTER DATA MAP(alloc:s_dprojections,vnl_dprojections) IF(gpu_option==ABI_GPU_OPENMP)
     674                 :             : #endif
     675         [ #  # ]:           0 :     if(gpu_option==ABI_GPU_DISABLED) then
     676   [ #  #  #  #  :           0 :       s_dprojections(:,:,:) = zero
                   #  # ]
     677   [ #  #  #  #  :           0 :       vnl_dprojections(:,:,:) = zero
                   #  # ]
     678         [ #  # ]:           0 :     else if(gpu_option==ABI_GPU_OPENMP) then
     679                 :           0 :       call gpu_set_to_zero(s_dprojections,   int(cplex,c_size_t)*ndgxdtfac*nprojs*ndat*nspinor)
     680                 :           0 :       call gpu_set_to_zero(vnl_dprojections, int(cplex_fac,c_size_t)*ndgxdtfac*nprojs*ndat*nspinor)
     681                 :             :     end if
     682                 :             :   else
     683   [ -  +  +  -  :       42462 :     ABI_MALLOC(s_dprojections,(1,1,ndat))
          +  -  +  -  -  
                +  -  + ]
     684   [ -  +  +  -  :       28308 :     ABI_MALLOC(vnl_dprojections,(1,1,ndat))
             -  +  -  + ]
     685                 :             :   end if
     686                 :             : 
     687                 :             :   ! Working buffers for storing 2nd-derivative
     688         [ -  + ]:       14154 :   if (nd2gxdt>0) then
     689   [ #  #  #  #  :           0 :     ABI_MALLOC(d2projections,(cplex, nd2gxdt*nprojs, nspinor*ndat))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     690                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     691                 :             :     !$OMP TARGET ENTER DATA MAP(alloc:d2projections) IF(gpu_option==ABI_GPU_OPENMP)
     692                 :             : #endif
     693         [ #  # ]:           0 :     if(cpopt < 4) then
     694         [ #  # ]:           0 :       if(gpu_option==ABI_GPU_DISABLED) then
     695   [ #  #  #  #  :           0 :         d2projections(:,:,:) = zero
                   #  # ]
     696         [ #  # ]:           0 :       else if(gpu_option==ABI_GPU_OPENMP) then
     697                 :           0 :         call gpu_set_to_zero(d2projections, int(cplex,c_size_t)*nd2gxdt*nprojs*ndat*nspinor)
     698                 :             :       end if
     699                 :             :     end if
     700                 :             :   else
     701   [ -  +  +  -  :       42462 :     ABI_MALLOC(d2projections,(1, 1, ndat))
          +  -  +  -  -  
                +  -  + ]
     702                 :             :   end if
     703                 :             : 
     704                 :             : 
     705                 :             :   ! determine precisely when temp_realvec_r~i needs to be allocated
     706                 :             :   ! to factorize allocate (resp. deallocate) at the begining (resp. at the end) of subroutine
     707                 :             :   ! to avoid multiple allocate/deallocate that can be costly
     708         [ +  + ]:       14154 :   if (cplex /= 2) then
     709                 :             :     if ( (cpopt < 2) .or. &
     710   [ -  +  -  -  :        4111 :       &  (paw_opt == 3 .or. paw_opt == 4) .or. &
                   -  - ]
     711                 :             :       &  (paw_opt == 0 .or. paw_opt == 1 .or. paw_opt == 4)) then
     712   [ -  +  +  -  :       12333 :        ABI_MALLOC(temp_realvec_r,(MAX(npwout,npwin)*nspinor*ndat))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     713   [ -  +  +  -  :        8222 :        ABI_MALLOC(temp_realvec_i,(MAX(npwout,npwin)*nspinor*ndat))
          -  +  -  +  -  
                      + ]
     714                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     715                 :             :        !$OMP TARGET ENTER DATA MAP(alloc:temp_realvec_r,temp_realvec_i) IF(gpu_option==ABI_GPU_OPENMP)
     716                 :             : #endif
     717                 :             :     end if
     718                 :             :   end if
     719                 :             : 
     720         [ +  + ]:       14154 :   if(cpopt >= 2) then
     721                 :             :     ! retrieve from cprjin
     722   [ +  +  +  - ]:         864 :     if(.not. local_vectproj .and. cpopt/=3) then
     723                 :             :       !$OMP PARALLEL DO PRIVATE(shift,idat,iatom,nlmn)
     724         [ +  + ]:        2016 :       do idat=1, ndat*nspinor
     725                 :             :         shift = 0
     726         [ +  + ]:        5472 :         do iatom = ia_beg, ia_end
     727                 :        3456 :           nlmn = cprjin(iatom, idat)%nlmn
     728   [ +  +  +  + ]:       86400 :           projections(1:cplex, shift+1:shift+nlmn, idat) = cprjin(iatom, idat)%cp(1:cplex, 1:nlmn)
     729                 :        5184 :           shift = shift + nlmn
     730                 :             :         end do
     731                 :             :       end do
     732                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     733                 :             :       !$OMP TARGET UPDATE TO(projections) IF(gpu_option==ABI_GPU_OPENMP)
     734                 :             : #endif
     735                 :             :     end if
     736   [ -  +  -  - ]:         864 :     if(cpopt==4.and.allocated(dprojections)) then
     737         [ #  # ]:           0 :       ABI_CHECK(cprjin(1,1)%ncpgr>=ndgxdt,"cprjin%ncpgr not correct! (1)")
     738                 :           0 :       ndgxdt_stored = cprjin(1,1)%ncpgr
     739                 :           0 :       ishift=0
     740   [ #  #  #  #  :           0 :       if (((choice==2).or.(choice==3)).and.(ndgxdt_stored>ndgxdt).and.(signs==2)) ishift=idir-ndgxdt
                   #  # ]
     741   [ #  #  #  #  :           0 :       if ((choice==2).and.(ndgxdt_stored==9).and.(signs==2)) ishift=ishift+6
                   #  # ]
     742   [ #  #  #  #  :           0 :       if (choice==2.and.(ndgxdt_stored>ndgxdt).and.(signs==1)) ishift=ndgxdt_stored-ndgxdt
                   #  # ]
     743                 :             :       !$OMP PARALLEL DO PRIVATE(shift,idat,iatom,igrad,nlmn)
     744         [ #  # ]:           0 :       do idat=1, ndat*nspinor
     745                 :             :         shift = 0
     746         [ #  # ]:           0 :         do iatom = ia_beg, ia_end
     747                 :           0 :           nlmn  = cprjin(iatom, idat)%nlmn
     748         [ #  # ]:           0 :           do ilmn=1,nlmn
     749         [ #  # ]:           0 :             do igrad=1,ndgxdt
     750                 :             :               dprojections(1:cplex, shift + igrad, idat) = &
     751         [ #  # ]:           0 :                 cprjin(iatom, idat)%dcp(1:cplex,igrad+ishift,ilmn)
     752                 :             :             end do
     753                 :           0 :             shift = shift + ndgxdt
     754                 :             :           end do
     755                 :             :         end do
     756                 :             :       end do
     757                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     758                 :             :       !$OMP TARGET UPDATE TO(dprojections) IF(gpu_option==ABI_GPU_OPENMP)
     759                 :             : #endif
     760                 :             :     end if
     761                 :             :   end if ! cpopt
     762                 :             : 
     763   [ +  +  +  -  :       14154 :   if(cpopt<=1.or.(cpopt<=3.and.(choice==2.or.choice==3.or.choice==5.or.choice==51.or.choice==23.or.choice==54.or.choice==55.or.choice==4))) then
                   -  + ]
     764                 :             : 
     765                 :             :     call opernla_gemm(choice,cplex,cplex_dgxdt,cplex_d2gxdt,dimffnlin,&
     766                 :             :     &       d2projections,dprojections,ffnlin,projections,&
     767                 :             :     &       idir,indlmn,istwf_k,kpgin_,matblk,mpi_enreg,nd2gxdt,ndgxdt,nkpgin_,&
     768                 :             :     &       npwin,nspinor,ph3din,signs,ucvol,ndat,ntypat,lmnmax,nattyp,(ikin==2),&
     769                 :             :     &       iatom_only,atom_proj_shift,cpopt,&
     770                 :             :     &       nprojs,&
     771                 :             :     &       vectin,&
     772                 :             :     &       temp_realvec_r,temp_realvec_i,&
     773                 :       13290 :     &       gpu_option,gemm_nonlop_is_distributed)
     774                 :             : 
     775         [ +  + ]:       13290 :     if(cpopt >= 0) then
     776                 :             :       ! store in cprjin
     777   [ +  +  +  - ]:        2780 :       if(.not. local_vectproj .and. cpopt/=3) then
     778                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     779                 :             :         !$OMP TARGET UPDATE FROM(projections) IF(gpu_option==ABI_GPU_OPENMP)
     780                 :             : #endif
     781                 :             :         !$OMP PARALLEL DO PRIVATE(shift,idat,iatom,nlmn)
     782         [ +  + ]:        5492 :         do idat=1, ndat*nspinor
     783                 :             :           shift = 0
     784         [ +  + ]:       12068 :           do iatom = ia_beg, ia_end
     785                 :        6576 :             nlmn = cprjin(iatom, idat)%nlmn
     786   [ +  +  +  + ]:      242656 :             cprjin(iatom, idat)%cp(1:cplex, 1:nlmn) = projections(1:cplex, shift+1:shift+nlmn, idat)
     787                 :        9864 :             shift = shift + nlmn
     788                 :             :           end do
     789                 :             :         end do
     790                 :             :       end if
     791         [ -  + ]:        2780 :       if(cpopt==1 .or. cpopt==3) then
     792         [ #  # ]:           0 :         ABI_CHECK(cprjin(1,1)%ncpgr>=ndgxdt,"cprjin%ncpgr not correct! (2)")
     793                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     794                 :             :         !$OMP TARGET UPDATE FROM(dprojections) IF(gpu_option==ABI_GPU_OPENMP)
     795                 :             : #endif
     796                 :             :         !$OMP PARALLEL DO PRIVATE(shift,idat,iatom,igrad,nlmn)
     797         [ #  # ]:           0 :         do idat=1, ndat*nspinor
     798                 :             :           shift = 0
     799         [ #  # ]:           0 :           do iatom = ia_beg, ia_end
     800                 :           0 :             nlmn = cprjin(iatom, idat)%nlmn
     801         [ #  # ]:           0 :             do ilmn=1,nlmn
     802         [ #  # ]:           0 :               do igrad=1,ndgxdt
     803                 :             :                 cprjin(iatom, idat)%dcp(1:cplex,igrad,ilmn) = &
     804         [ #  # ]:           0 :                 &                   dprojections(1:cplex, shift + igrad, idat)
     805                 :             :               end do
     806                 :           0 :               shift = shift + ndgxdt
     807                 :             :             end do
     808                 :             :           end do
     809                 :             :         end do
     810                 :             :       end if
     811                 :             :     end if ! cpopt >= 0
     812                 :             :   end if ! cpopt >= 2
     813                 :             : 
     814         [ +  + ]:       14154 :   if(choice > 0) then
     815                 :             : 
     816         [ +  + ]:       11422 :     if(choice /= 7) then
     817                 :             :       ! opernlc
     818                 :       10846 :       iatm = 0
     819                 :       10846 :       shift = 0; dshift = 0; dfshift = 0; d2shift = 0
     820         [ +  + ]:       29342 :       do itypat=1, ntypat_
     821   [ +  +  +  + ]:      319464 :         nlmn=count(indlmn_(3,:,itypat)>0)
     822                 :             : 
     823                 :       18496 :         ibeg = shift+1
     824                 :       18496 :         iend = shift+nattyp_(itypat)*nlmn
     825                 :             : 
     826                 :       18496 :         idbeg = dshift+1
     827                 :       18496 :         idend = dshift+nattyp_(itypat)*nlmn*ngrads
     828                 :             : 
     829                 :       18496 :         idfbeg = dshift+1
     830                 :       18496 :         idfend = dshift+nattyp_(itypat)*nlmn*ndgxdtfac
     831                 :             : 
     832                 :       18496 :         id2beg = d2shift+1
     833                 :       18496 :         id2end = d2shift+nattyp_(itypat)*nlmn*ngrads2
     834                 :             : 
     835                 :             :         call opernlc_ylm_allwf(atindx1_,cplex,cplex_dgxdt,cplex_d2gxdt,&
     836                 :             :         &         cplex_enl,cplex_fac,&
     837                 :             :         &         dprojections,&
     838                 :             :         &         vnl_dprojections,&
     839                 :             :         &         s_dprojections,&
     840                 :             :         &         d2projections,d2gxdt_dum_out,d2gxdt_dum_out2,&
     841                 :             :         &         dimenl1,dimenl2_,dimekbq,enl_,&
     842                 :             :         &         projections,&
     843                 :             :         &         vnl_projections,&
     844                 :             :         &         s_projections,&
     845                 :             :         &         iatm,indlmn_(:,:,itypat),itypat,lambda,mpi_enreg,natom_,&
     846                 :             :         &         ndgxdt,ndgxdtfac,nd2gxdt,nd2gxdtfac,&
     847                 :             :         &         nattyp_(itypat),nlmn,nspinor,nspinortot,optder,paw_opt,sij_typ(:,itypat),&
     848                 :       18496 :         &         ndat,ibeg-1,iend,nprojs,ndat_enl,gpu_option)
     849                 :             : 
     850                 :       18496 :         shift = shift + nattyp_(itypat)*nlmn
     851                 :       18496 :         dshift = dshift + nattyp_(itypat)*nlmn*ngrads
     852                 :       18496 :         dfshift = dshift + nattyp_(itypat)*nlmn*ndgxdtfac
     853                 :       18496 :         d2shift = d2shift + nattyp_(itypat)*nlmn*ngrads2
     854                 :       29342 :         iatm = iatm+nattyp_(itypat)
     855                 :             :       end do
     856                 :             :     else
     857         [ +  - ]:         576 :       if(gpu_option==ABI_GPU_DISABLED) then
     858   [ +  -  +  -  :      128160 :         s_projections = projections
          +  -  -  +  -  
          -  +  +  +  +  
                   +  + ]
     859         [ #  # ]:           0 :       else if(gpu_option==ABI_GPU_OPENMP) then
     860                 :           0 :         call gpu_copy(s_projections, projections, int(cplex,c_size_t) * nprojs * nspinor * ndat)
     861                 :             :       end if
     862                 :             :     end if ! choice /= 7
     863                 :             : 
     864                 :             :     ! opernlb
     865         [ +  + ]:       11422 :     if(signs==2) then
     866                 :             : 
     867                 :             :       call opernlb_gemm(choice,cplex,cplex_dgxdt,cplex_d2gxdt,cplex_fac,&
     868                 :             :       &       d2gxdt_dum_in,d2gxdt_dum_out,&
     869                 :             :       &       vnl_dprojections,s_dprojections,dimffnlout,ffnlout,&
     870                 :             :       &       vnl_projections,s_projections,&
     871                 :             :       &       idir,indlmn,kpgout_,matblk,istwf_k,&
     872                 :             :       &       nd2gxdt,nd2gxdtfac,ndgxdt,ndgxdtfac,&
     873                 :             :       &       nkpgout_,npwout,nspinor,signs,ucvol,ndat,&
     874                 :             :       &       ntypat,lmnmax,nattyp,(ikout==2),iatom_only,atom_proj_shift,&
     875                 :             :       &       paw_opt,ph3dout,&
     876                 :             :       &       nprojs,&
     877                 :             :       &       vectin_,vectout_,svectout_,&
     878                 :             :       &       temp_realvec_r,temp_realvec_i,&
     879                 :       10902 :       &       gpu_option,gemm_nonlop_is_distributed)
     880                 :             :     end if
     881                 :             : 
     882                 :             :     ! opernld
     883         [ +  + ]:       11422 :     if(signs==1) then
     884                 :         520 :       nld_on_gpu = .false.
     885         [ +  - ]:         520 :       if(choice==1 .or. choice==2 .or. choice==3 .or. choice==23 .or. choice==4 .or. choice==54 .or. choice==55 .or. choice==6) then
     886                 :         520 :         if(gpu_option==ABI_GPU_OPENMP) nld_on_gpu = .true.
     887                 :             :         call opernld_ylm_allwf(choice,cplex,cplex_fac,ddkk,&
     888                 :             :         &       dprojections,vnl_dprojections,s_dprojections,d2projections,&
     889                 :             :         &       enlk,enlout,fnlk,projections,vnl_projections,s_projections,&
     890                 :             :         &       natom,ndat,nd2gxdt,ndgxdt,&
     891                 :             :         &       ndgxdtfac,indlmn_,ntypat_,lmnmax,nprojs,nnlout,nspinor,paw_opt,&
     892                 :         520 :         &       strnlk,nattyp_,gpu_option)
     893                 :             :       else
     894                 :           0 :         shift=0; dshift=0; dfshift = 0; d2shift = 0; iatm=1
     895                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     896                 :             :         !$OMP TARGET UPDATE FROM(dprojections,vnl_dprojections,s_dprojections) IF(gpu_option==ABI_GPU_OPENMP)
     897                 :             :         !$OMP TARGET UPDATE FROM(d2projections) IF(gpu_option==ABI_GPU_OPENMP)
     898                 :             :         !$OMP TARGET UPDATE FROM(projections,vnl_projections,s_projections) IF(gpu_option==ABI_GPU_OPENMP)
     899                 :             : #endif
     900         [ #  # ]:           0 :         do itypat=1, ntypat_
     901   [ #  #  #  # ]:           0 :           nlmn=count(indlmn_(3,:,itypat)>0)
     902                 :             : 
     903                 :           0 :           ibeg = shift+1
     904                 :           0 :           iend = shift+nattyp_(itypat)*nlmn
     905                 :             : 
     906                 :           0 :           idbeg = dshift+1
     907                 :           0 :           idend = dshift+nattyp_(itypat)*nlmn*ngrads
     908                 :             : 
     909                 :           0 :           idfbeg = dshift+1
     910                 :           0 :           idfend = dshift+nattyp_(itypat)*nlmn*ndgxdtfac
     911                 :             : 
     912                 :           0 :           id2beg = d2shift+1
     913                 :           0 :           id2end = d2shift+nattyp_(itypat)*nlmn*ngrads2
     914                 :             : 
     915         [ #  # ]:           0 :           do idat=1,ndat
     916                 :             :             call opernld_ylm             (choice,cplex,cplex_fac,ddkk(:,idat),&
     917                 :             :             &       dprojections    (:, idbeg:idend, 1+nspinor*(idat-1):nspinor*idat),&
     918                 :             :             &       vnl_dprojections(:, idfbeg:idfend, 1+nspinor*(idat-1):nspinor*idat),&
     919                 :             :             &       s_dprojections  (:, idfbeg:idfend, 1+nspinor*(idat-1):nspinor*idat),&
     920                 :             :             &       d2projections (:, id2beg:id2end, 1+nspinor*(idat-1):nspinor*idat),&
     921                 :             :             &       enlk(idat),enlout(nnlout*(idat-1)+1:nnlout*idat),fnlk(:,idat),&
     922                 :             :             &       projections    (:, ibeg:iend, 1+nspinor*(idat-1):nspinor*idat),&
     923                 :             :             &       vnl_projections(:, ibeg:iend, 1+nspinor*(idat-1):nspinor*idat),&
     924                 :             :             &       s_projections  (:, ibeg:iend, 1+nspinor*(idat-1):nspinor*idat),&
     925                 :             :             &       iatm,natom_,1,nd2gxdt,ndgxdt,ndgxdtfac,&
     926   [ #  #  #  #  :           0 :             &       nattyp_(itypat),nlmn,nnlout,nspinor,paw_opt,strnlk(:,idat))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     927                 :             :           end do
     928                 :             : 
     929                 :           0 :           shift = shift + nattyp_(itypat)*nlmn
     930                 :           0 :           dshift = dshift + nattyp_(itypat)*nlmn*ngrads
     931                 :           0 :           dfshift = dshift + nattyp_(itypat)*nlmn*ndgxdtfac
     932                 :           0 :           d2shift = d2shift + nattyp_(itypat)*nlmn*ngrads2
     933                 :           0 :           iatm = iatm+nattyp_(itypat)
     934                 :             :         end do
     935                 :             :       end if
     936                 :             : 
     937                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     938                 :             :       !$OMP TARGET UPDATE FROM(enlout) if(nld_on_gpu)
     939                 :             : #endif
     940                 :             : 
     941                 :             :       ! Reduction in case of parallelism
     942         [ -  + ]:         520 :       if (mpi_enreg%paral_spinor==1) then
     943         [ #  # ]:           0 :         if (size(enlout)>0) then
     944                 :           0 :           call xmpi_sum(enlout,mpi_enreg%comm_spinor,ierr)
     945                 :             :         end if
     946         [ #  # ]:           0 :         if (choice==3.or.choice==23) then
     947                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     948                 :             :           !$OMP TARGET UPDATE FROM(enlk) if(nld_on_gpu)
     949                 :             : #endif
     950                 :           0 :           call xmpi_sum(enlk,mpi_enreg%comm_spinor,ierr)
     951                 :             :         end if
     952         [ #  # ]:           0 :         if (choice==55) then
     953                 :           0 :           call xmpi_sum(ddkk,mpi_enreg%comm_spinor,ierr)
     954                 :             :         end if
     955                 :             :       end if
     956                 :             : 
     957                 :             :       !Need sometimes gmet
     958   [ +  -  +  -  :         520 :       if ((signs==1.and.paw_opt<=3).and. &
          +  -  +  -  +  
                -  +  - ]
     959                 :             :           & (choice==5 .or.choice==51.or.choice==52.or.choice==53.or.&
     960                 :             :           & choice==54.or.choice==55)) then
     961         [ #  # ]:           0 :         ABI_MALLOC(gmet2,(3,3))
     962   [ -  -  -  -  :         520 :         gmet2 = MATMUL(TRANSPOSE(gprimd),gprimd)
          -  -  -  -  -  
          -  -  -  -  -  
                   -  - ]
     963                 :             :       end if
     964                 :             : 
     965                 :             :       !Coordinate transformations
     966                 :             : 
     967                 :             :       ! Derivatives wrt strain
     968                 :             :       !  - Convert from reduced to cartesian coordinates
     969                 :             :       !  - Substract volume contribution
     970   [ +  +  +  - ]:         520 :       if ((choice==3.or.choice==23).and.paw_opt<=3) then
     971                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     972                 :             :         !$OMP TARGET UPDATE FROM(enlk) if(nld_on_gpu)
     973                 :             : #endif
     974         [ +  + ]:         980 :         do idat=1,ndat
     975                 :         768 :           enlout_shift=(idat-1)*nnlout
     976                 :         768 :           call strconv(enlout(enlout_shift+1:enlout_shift+6),gprimd,work)
     977         [ +  + ]:        3072 :           enlout(enlout_shift+1:enlout_shift+3)=(work(1:3)-enlk(idat))
     978         [ +  + ]:        3284 :           enlout(enlout_shift+4:enlout_shift+6)= work(4:6)
     979                 :             :         end do
     980                 :             :       end if
     981                 :             : 
     982                 :             :       !2nd derivative wrt to k wave vector and atomic position (effective charges):
     983                 :             :       ! - convert from cartesian to reduced coordinates
     984   [ -  +  -  - ]:         520 :       if (choice==54.and.signs==1.and.paw_opt<=3) then
     985         [ #  # ]:           0 :         ABI_MALLOC(work1,(3))
     986         [ #  # ]:           0 :         ABI_MALLOC(work2,(3))
     987         [ #  # ]:           0 :         do idat=1,ndat
     988                 :           0 :           mu0=0 ! Shift to be applied in enlout array
     989                 :           0 :           enlout_shift=(idat-1)*nnlout
     990         [ #  # ]:           0 :           do mu=1,3*natom
     991                 :             :         !   First, real part
     992                 :           0 :             work1(1)=enlout(enlout_shift+mu0+1);work1(2)=enlout(enlout_shift+mu0+3);work1(3)=enlout(enlout_shift+mu0+5)
     993         [ #  # ]:           0 :             work2(:)=gmet2(:,1)*work1(1)+gmet2(:,2)*work1(2)+gmet2(:,3)*work1(3)
     994                 :           0 :             enlout(enlout_shift+mu0+1)=work2(1);enlout(enlout_shift+mu0+3)=work2(2);enlout(enlout_shift+mu0+5)=work2(3)
     995                 :             :         !   Then imaginary part
     996                 :           0 :             work1(1)=enlout(enlout_shift+mu0+2);work1(2)=enlout(enlout_shift+mu0+4);work1(3)=enlout(enlout_shift+mu0+6)
     997         [ #  # ]:           0 :             work2(:)=gmet2(:,1)*work1(1)+gmet2(:,2)*work1(2)+gmet2(:,3)*work1(3)
     998                 :           0 :             enlout(enlout_shift+mu0+2)=work2(1);enlout(enlout_shift+mu0+4)=work2(2);enlout(enlout_shift+mu0+6)=work2(3)
     999                 :           0 :             mu0=mu0+6
    1000                 :             :           end do
    1001                 :             :         end do !idat
    1002         [ #  # ]:           0 :         ABI_FREE(work1)
    1003         [ #  # ]:           0 :         ABI_FREE(work2)
    1004                 :             :       end if
    1005                 :             : 
    1006                 :             :       !2nd derivative wrt to k wave vector and strain (piezoelectric tensor):
    1007                 :             :       ! - convert from cartesian to reduced coordinates (k point)
    1008                 :             :       ! - convert from reduced to cartesian coordinates (strain)
    1009                 :             :       ! - substract volume contribution
    1010                 :             :       ! - symetrize strain components
    1011   [ -  +  -  -  :         520 :       if (choice==55.and.signs==1.and.paw_opt<=3) then
                   -  - ]
    1012                 :             : #ifdef HAVE_OPENMP_OFFLOAD
    1013                 :             :         !$OMP TARGET UPDATE FROM(ddkk) if(nld_on_gpu)
    1014                 :             : #endif
    1015         [ #  # ]:           0 :         ABI_MALLOC(work3,(2,3))
    1016         [ #  # ]:           0 :         ABI_MALLOC(work4,(2,3))
    1017         [ #  # ]:           0 :         ABI_MALLOC(work5,(2,3,6))
    1018         [ #  # ]:           0 :         ABI_MALLOC(work7,(2,3,6))
    1019         [ #  # ]:           0 :         ABI_MALLOC(work6,(2,3,3))
    1020         [ #  # ]:           0 :         do idat=1,ndat
    1021                 :           0 :           enlout_shift=(idat-1)*nnlout
    1022         [ #  # ]:           0 :           do ic=1,3 ! gamma
    1023   [ #  #  #  #  :           0 :             work5=zero
                   #  # ]
    1024         [ #  # ]:           0 :             do jc=1,3 ! nu
    1025         [ #  # ]:           0 :               do ii=1,3 ! lambda
    1026                 :           0 :                 mu=(gamma(jc,ii)-1)*3+1
    1027                 :             :                 work5(1,jc,ii)=gmet2(ic,1)*enlout(enlout_shift+2*mu-1)+gmet2(ic,2)*enlout(enlout_shift+2*mu+1) &
    1028                 :           0 :        &         +gmet2(ic,3)*enlout(enlout_shift+2*mu+3)
    1029                 :             :                 work5(2,jc,ii)=gmet2(ic,1)*enlout(enlout_shift+2*mu  )+gmet2(ic,2)*enlout(enlout_shift+2*mu+2) &
    1030                 :           0 :        &         +gmet2(ic,3)*enlout(enlout_shift+2*mu+4)
    1031                 :             :               end do
    1032                 :             :             end do
    1033   [ #  #  #  #  :           0 :             work6=zero
                   #  # ]
    1034         [ #  # ]:           0 :             do jc=1,3 ! nu
    1035         [ #  # ]:           0 :               do ii=1,3 ! beta
    1036                 :             :                 work6(1:cplex,ii,jc)=gprimd(ii,1)*work5(1:cplex,jc,1)+gprimd(ii,2)*work5(1:cplex,jc,2) &
    1037         [ #  # ]:           0 :        &         +gprimd(ii,3)*work5(1:cplex,jc,3)
    1038                 :             :               end do
    1039                 :             :             end do
    1040         [ #  # ]:           0 :             do jc=1,3 ! alpha
    1041         [ #  # ]:           0 :               do ii=1,3 ! beta
    1042                 :           0 :                 mu=gamma(jc,ii)
    1043                 :             :                 work7(1:cplex,ic,mu)=gprimd(jc,1)*work6(1:cplex,ii,1)+gprimd(jc,2)*work6(1:cplex,ii,2) &
    1044         [ #  # ]:           0 :        &         +gprimd(jc,3)*work6(1:cplex,ii,3)
    1045                 :             :               end do
    1046                 :             :             end do
    1047                 :             :           end do ! gamma
    1048                 :             : 
    1049         [ #  # ]:           0 :           do ii=1,3 ! alpha
    1050                 :             :             work3(1,ii)=gprimd(ii,1)*ddkk(2*1-1,idat)+gprimd(ii,2)*ddkk(2*2-1,idat) &
    1051                 :           0 :        &     +gprimd(ii,3)*ddkk(2*3-1,idat)
    1052                 :             :             work3(2,ii)=gprimd(ii,1)*ddkk(2*1  ,idat)+gprimd(ii,2)*ddkk(2*2  ,idat) &
    1053                 :           0 :        &     +gprimd(ii,3)*ddkk(2*3  ,idat)
    1054                 :             :           end do
    1055         [ #  # ]:           0 :           do ii=1,3 ! gamma
    1056                 :             :             work4(1,ii)=gmet2(ii,1)*ddkk(2*1-1,idat)+gmet2(ii,2)*ddkk(2*2-1,idat) &
    1057                 :           0 :        &     +gmet2(ii,3)*ddkk(2*3-1,idat)
    1058                 :             :             work4(2,ii)=gmet2(ii,1)*ddkk(2*1  ,idat)+gmet2(ii,2)*ddkk(2*2  ,idat) &
    1059                 :           0 :        &     +gmet2(ii,3)*ddkk(2*3  ,idat)
    1060                 :             :           end do
    1061                 :             : 
    1062         [ #  # ]:           0 :           do mu=1,6
    1063                 :           0 :             ii=alpha(mu) ! alpha
    1064                 :           0 :             ic=beta(mu) ! beta
    1065         [ #  # ]:           0 :             do jc=1,3 ! gamma
    1066                 :             :               work7(1:cplex,jc,mu)=work7(1:cplex,jc,mu)-half &
    1067         [ #  # ]:           0 :        &       *(gprimd(ic,jc)*work3(1:cplex,ii)+gprimd(ii,jc)*work3(1:cplex,ic))
    1068   [ #  #  #  # ]:           0 :               if (ii==ic) work7(1:cplex,jc,mu)=work7(1:cplex,jc,mu)-work4(1:cplex,jc)
    1069                 :             :             end do
    1070                 :             :           end do
    1071         [ #  # ]:           0 :           do mu=1,6 ! alpha,beta
    1072         [ #  # ]:           0 :             do nu=1,3 ! gamma
    1073                 :           0 :               mu0=3*(mu-1)+nu
    1074                 :           0 :               enlout(enlout_shift+2*mu0-1)=work7(1,nu,mu)
    1075                 :           0 :               enlout(enlout_shift+2*mu0  )=work7(2,nu,mu)
    1076                 :             :             end do
    1077                 :             :           end do
    1078                 :             :         end do !idat
    1079         [ #  # ]:           0 :         ABI_FREE(work3)
    1080         [ #  # ]:           0 :         ABI_FREE(work4)
    1081         [ #  # ]:           0 :         ABI_FREE(work5)
    1082         [ #  # ]:           0 :         ABI_FREE(work6)
    1083         [ #  # ]:           0 :         ABI_FREE(work7)
    1084                 :             :       end if
    1085                 :             : 
    1086                 :             : 
    1087                 :             :      !2nd derivative wrt to 2 strains (elastic tensor):
    1088                 :             :      ! - convert from reduced to cartesian coordinates
    1089                 :             :      ! - substract volume contribution
    1090   [ -  +  -  -  :         520 :       if (choice==6.and.signs==1.and.paw_opt<=3) then
                   -  - ]
    1091                 :             : #ifdef HAVE_OPENMP_OFFLOAD
    1092                 :             :         !$OMP TARGET UPDATE FROM(enlk,strnlk,fnlk) if(nld_on_gpu)
    1093                 :             : #endif
    1094         [ #  # ]:           0 :         ABI_MALLOC(work1,(6))
    1095         [ #  # ]:           0 :         ABI_MALLOC(work2,(6))
    1096   [ #  #  #  #  :           0 :         ABI_MALLOC(work3,(6+3*natom,6))
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1097         [ #  # ]:           0 :         do idat=1,ndat
    1098                 :           0 :           mu0=(idat-1)*nnlout ! Shift to be applied in enlout array
    1099         [ #  # ]:           0 :           work3(:,:)=reshape(enlout(mu0+1:mu0+6*(6+3*natom)),(/6+3*natom,6/))
    1100         [ #  # ]:           0 :           do mu=1,6
    1101                 :           0 :             call strconv(work3(1:6,mu),gprimd,work3(1:6,mu))
    1102                 :             :           end do
    1103         [ #  # ]:           0 :           do mu=1,6+3*natom
    1104         [ #  # ]:           0 :             work1(1:6)=work3(mu,1:6)
    1105                 :           0 :             call strconv(work1,gprimd,work2)
    1106         [ #  # ]:           0 :             work3(mu,1:6)=work2(1:6)
    1107                 :             :           end do
    1108         [ #  # ]:           0 :           enlout(mu0+1:mu0+6*(6+3*natom))=reshape(work3(:,:),(/6*(6+3*natom)/))
    1109                 :           0 :           call strconv(strnlk(:,idat),gprimd,strnlk(:,idat))
    1110         [ #  # ]:           0 :           do mub=1,6
    1111                 :           0 :             nub1=alpha(mub);nub2=beta(mub)
    1112         [ #  # ]:           0 :             do mua=1,6
    1113                 :           0 :               mu=mu0+mua+(3*natom+6)*(mub-1)
    1114                 :           0 :               nua1=alpha(mua);nua2=beta(mua)
    1115         [ #  # ]:           0 :               if (mua<=3.and.mub<=3) enlout(mu)=enlout(mu)+enlk(idat)
    1116         [ #  # ]:           0 :               if (mua<=3) enlout(mu)=enlout(mu)-strnlk(mub,idat)
    1117         [ #  # ]:           0 :               if (mub<=3) enlout(mu)=enlout(mu)-strnlk(mua,idat)
    1118         [ #  # ]:           0 :               if (nub1==nua2) enlout(mu)=enlout(mu)-0.25d0*strnlk(gamma(nua1,nub2),idat)
    1119         [ #  # ]:           0 :               if (nub2==nua2) enlout(mu)=enlout(mu)-0.25d0*strnlk(gamma(nua1,nub1),idat)
    1120         [ #  # ]:           0 :               if (nub1==nua1) enlout(mu)=enlout(mu)-0.25d0*strnlk(gamma(nua2,nub2),idat)
    1121         [ #  # ]:           0 :               if (nub2==nua1) enlout(mu)=enlout(mu)-0.25d0*strnlk(gamma(nua2,nub1),idat)
    1122                 :             :             end do
    1123         [ #  # ]:           0 :             if (mub<=3) then
    1124         [ #  # ]:           0 :               do nua1=1,natom
    1125                 :           0 :                 nua2=3*(nua1-1);mu=mu0+nua2+6+(3*natom+6)*(mub-1)
    1126         [ #  # ]:           0 :                 enlout(mu+1:mu+3)=enlout(mu+1:mu+3)-fnlk(nua2+1:nua2+3,idat)
    1127                 :             :               end do
    1128                 :             :             end if
    1129                 :             :           end do
    1130                 :             :         end do
    1131         [ #  # ]:           0 :         ABI_FREE(work1)
    1132         [ #  # ]:           0 :         ABI_FREE(work2)
    1133         [ #  # ]:           0 :         ABI_FREE(work3)
    1134                 :             :       end if
    1135                 :             : 
    1136                 :             :     end if !opernld
    1137                 :             : 
    1138                 :             :   end if ! choice>0
    1139                 :             : 
    1140                 :             : #ifdef HAVE_OPENMP_OFFLOAD
    1141                 :             :   if(gpu_option==ABI_GPU_OPENMP) then
    1142                 :             :     ! Retrieve and release allocated buffers
    1143                 :             :     !$OMP TARGET EXIT DATA MAP(delete:vectin) IF(transfer_vectin)
    1144                 :             :     !$OMP TARGET EXIT DATA MAP(from:vectout)   IF(transfer_vectout)
    1145                 :             :     !$OMP TARGET EXIT DATA MAP(from:svectout)  IF(transfer_svectout)
    1146                 :             : 
    1147                 :             :     !$OMP TARGET EXIT DATA MAP(delete:s_projections,vnl_projections)
    1148                 :             :     !$OMP TARGET EXIT DATA MAP(delete:projections)     IF(.not. local_vectproj)
    1149                 :             :     !$OMP TARGET EXIT DATA MAP(delete:dprojections)     IF(ndgxdt>0)
    1150                 :             :     !$OMP TARGET EXIT DATA MAP(delete:s_dprojections)   IF(ndgxdtfac>0)
    1151                 :             :     !$OMP TARGET EXIT DATA MAP(delete:vnl_dprojections) IF(ndgxdtfac>0)
    1152                 :             :     !$OMP TARGET EXIT DATA MAP(delete:d2projections)    IF(nd2gxdt>0)
    1153                 :             : 
    1154                 :             :     if (cplex /= 2) then
    1155                 :             :       if ( (cpopt < 2) .or. &
    1156                 :             :         &  (paw_opt == 3 .or. paw_opt == 4) .or. &
    1157                 :             :         &  (paw_opt == 0 .or. paw_opt == 1 .or. paw_opt == 4)) then
    1158                 :             :         !$OMP TARGET EXIT DATA MAP(delete:temp_realvec_r,temp_realvec_i)
    1159                 :             :       end if
    1160                 :             :     end if
    1161                 :             : 
    1162                 :             :     if(size(enl_)>0) then
    1163                 :             :       !$OMP TARGET EXIT DATA MAP(delete:enl_)
    1164                 :             :     end if
    1165                 :             : 
    1166                 :             :     if(paw_opt>=2 .and. choice > 0 .and. choice /= 7) then
    1167                 :             :       !$OMP TARGET EXIT DATA MAP(delete:sij_typ) IF(gpu_option==ABI_GPU_OPENMP)
    1168                 :             :     end if
    1169                 :             : 
    1170                 :             :     !$OMP TARGET EXIT DATA MAP(delete:kpgin_)  IF(nkpgin_  > 0)
    1171                 :             :     !$OMP TARGET EXIT DATA MAP(delete:kpgout_) IF(nkpgout_ > 0)
    1172                 :             : 
    1173                 :             :     !$OMP TARGET EXIT DATA MAP(delete:enlk,fnlk,strnlk,ddkk,enlout) IF(signs == 1 .and. choice > 0)
    1174                 :             :     !$OMP TARGET EXIT DATA MAP(delete:atindx1,indlmn)
    1175                 :             :   end if
    1176                 :             : #endif
    1177                 :             : 
    1178                 :             : ! Release memory
    1179                 :             : 
    1180         [ -  + ]:       14154 :   if (iatom_only>0) then
    1181         [ #  # ]:           0 :     ABI_FREE(atindx1_)
    1182         [ #  # ]:           0 :     ABI_FREE(nattyp_)
    1183         [ #  # ]:           0 :     ABI_FREE(ph3din_)
    1184         [ #  # ]:           0 :     ABI_FREE(ph3dout_)
    1185         [ #  # ]:           0 :     ABI_FREE(ffnlin_)
    1186         [ #  # ]:           0 :     ABI_FREE(ffnlout_)
    1187         [ #  # ]:           0 :     ABI_FREE(enl_)
    1188         [ #  # ]:           0 :     ABI_FREE(indlmn_)
    1189   [ #  #  #  # ]:           0 :     if (size(sij) > 1) then
    1190         [ #  # ]:           0 :       ABI_FREE(sij_)
    1191                 :             :     end if
    1192                 :             :   end if
    1193                 :             : 
    1194   [ +  +  +  + ]:       14154 :   if(signs == 1 .and. choice > 0) then
    1195                 :             : #ifdef HAVE_OPENMP_OFFLOAD
    1196                 :             : #endif
    1197         [ -  + ]:         520 :     ABI_FREE(enlk)
    1198         [ -  + ]:         520 :     ABI_FREE(fnlk)
    1199         [ -  + ]:         520 :     ABI_FREE(strnlk)
    1200         [ -  + ]:         520 :     ABI_FREE(ddkk)
    1201                 :             :   end if
    1202                 :             : 
    1203         [ +  + ]:       14154 :   if (nkpgin<nkpgin_) then
    1204         [ -  + ]:          64 :     ABI_FREE(kpgin_)
    1205                 :             :   end if
    1206         [ -  + ]:       14154 :   if (nkpgout<nkpgout_) then
    1207         [ #  # ]:           0 :     ABI_FREE(kpgout_)
    1208                 :             :   end if
    1209                 :             : 
    1210         [ -  + ]:       14154 :   if (allocated(gmet2)) then
    1211                 :           0 :     ABI_FREE(gmet2)
    1212                 :             :   end if
    1213                 :             : 
    1214         [ +  - ]:       14154 :   if (allocated(sij_typ)) then
    1215                 :       14154 :     ABI_FREE(sij_typ)
    1216                 :             :   end if
    1217                 :             : 
    1218         [ -  + ]:       14154 :   ABI_FREE(cplex_dgxdt)
    1219         [ -  + ]:       14154 :   ABI_FREE(cplex_d2gxdt)
    1220                 :             : 
    1221         [ +  + ]:       14154 :   if(.not. local_vectproj) then
    1222         [ -  + ]:       13002 :     ABI_FREE(projections)
    1223                 :             :   end if
    1224         [ -  + ]:       14154 :   ABI_FREE(s_projections)
    1225         [ -  + ]:       14154 :   ABI_FREE(vnl_projections)
    1226         [ +  - ]:       14154 :   if (allocated(dprojections)) then
    1227                 :       14154 :     ABI_FREE(dprojections)
    1228                 :             :   end if
    1229         [ +  - ]:       14154 :   if (allocated(s_dprojections)) then
    1230                 :       14154 :     ABI_FREE(s_dprojections)
    1231                 :             :   end if
    1232         [ +  - ]:       14154 :   if (allocated(vnl_dprojections)) then
    1233                 :       14154 :     ABI_FREE(vnl_dprojections)
    1234                 :             :   end if
    1235         [ +  - ]:       14154 :   if (allocated(d2projections)) then
    1236                 :       14154 :     ABI_FREE(d2projections)
    1237                 :             :   end if
    1238         [ +  + ]:       14154 :   if (allocated(temp_realvec_r)) then
    1239                 :        4111 :     ABI_FREE(temp_realvec_r)
    1240         [ -  + ]:        4111 :     ABI_FREE(temp_realvec_i)
    1241                 :             :   end if
    1242                 :             : 
    1243   [ -  +  -  +  :       28308 :  end subroutine gemm_nonlop
          -  +  -  +  -  
             +  -  +  -  
                      + ]
    1244                 :             : !***
    1245                 :             : 
    1246                 :             : end module m_gemm_nonlop
    1247                 :             : !!***
        

Generated by: LCOV version 2.3-1