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-09-19 17:42:43 Functions: 33.3 % 3 1

            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),ABI_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, ABI_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), ABI_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, ABI_CONTIGUOUS pointer :: atindx1_(:),indlmn_(:,:,:),nattyp_(:)
     252        14154 :   real(dp),pointer :: ffnlin_(:,:,:,:),ffnlout_(:,:,:,:)
     253        14154 :   real(dp),pointer :: ph3din_(:,:,:),ph3dout_(:,:,:)
     254        14154 :   real(dp), ABI_CONTIGUOUS pointer :: enl_(:,:,:,:,:)
     255        14154 :   real(dp), ABI_CONTIGUOUS pointer :: sij_(:,:)
     256        14154 :   real(dp), ABI_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