LCOV - code coverage report
Current view: top level - src/66_wfs - m_fock_getghc.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 88.0 % 752 662
Test Date: 2026-09-21 19:39:32 Functions: 75.0 % 4 3

            Line data    Source code
       1              : !!****m* ABINIT/m_fock_getghc
       2              : !! NAME
       3              : !!
       4              : !! FUNCTION
       5              : !!
       6              : !! COPYRIGHT
       7              : !!  Copyright (C) 2013-2026 ABINIT group (CMartins, FJ, MT, XG)
       8              : !!  This file is distributed under the terms of the
       9              : !!  GNU General Public License, see ~abinit/COPYING
      10              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      11              : !!
      12              : !! SOURCE
      13              : 
      14              : #if defined HAVE_CONFIG_H
      15              : #include "config.h"
      16              : #endif
      17              : 
      18              : #include "abi_common.h"
      19              : 
      20              : module m_fock_getghc
      21              : 
      22              :  use, intrinsic :: iso_c_binding, only: c_size_t, c_loc
      23              :  use defs_basis
      24              :  use m_abicore
      25              :  use m_errors
      26              :  use m_xmpi
      27              :  use m_fock
      28              :  use m_pawcprj
      29              :  !use m_cgtools
      30              : 
      31              :  use defs_abitypes, only : mpi_type
      32              :  use defs_datatypes, only : pseudopotential_type
      33              :  use m_time,         only : timab, time_accu
      34              :  use m_matrix,       only : matr3inv
      35              :  use m_cgtools,      only : dotprod_g,dotprod_g_batch_half,dotprod_g_batch_full
      36              :  use m_kg,           only : mkkpg
      37              :  use m_fftcore,      only : sphereboundary
      38              :  use m_fft,          only : fftpac, fourwf, fourdp
      39              :  use m_fstrings,     only : sjoin, itoa
      40              :  use m_hamiltonian,  only : gs_hamiltonian_type, K_H_KPRIME
      41              :  use m_paw_nhat,     only : pawmknhat_psipsi_ndat, pawdijhat_ndat
      42              :  use m_spacepar,     only : hartre
      43              :  use m_nonlop,       only : nonlop
      44              :  use m_bandfft_kpt,      only : bandfft_kpt, bandfft_kpt_type, bandfft_kpt_savetabs,bandfft_kpt_restoretabs, &
      45              :                                 prep_bandfft_tabs
      46              :  use m_pawtab,           only : pawtab_type
      47              :  use m_paw_ij,           only : paw_ij_type
      48              :  use m_mkffnl,           only : mkffnl
      49              :  use m_mpinfo,           only : proc_distrb_cycle
      50              :  use m_gputk
      51              :  use m_abi_linalg
      52              : 
      53              : #if defined(HAVE_GPU)
      54              :  use m_gpu_toolbox
      55              : #endif
      56              : 
      57              :  implicit none
      58              : 
      59              :  private
      60              : !!***
      61              : 
      62              :  public :: fock_getghc
      63              :  public :: fock2ACE
      64              :  public :: fock_ACE_getghc
      65              : !!***
      66              : 
      67              : contains
      68              : !!***
      69              : 
      70            0 : subroutine select_ndat_occ_for_gpu(ndat_occ,nband_k,ndat,npw,cplex_fock,nfftf,ngfft,&
      71            0 :     n4,n5,n6,natom,nspinor,lmn2_size,usepaw,cprj,ieigen,need_ghc,optfor,optstr,nfgd_max)
      72              : 
      73              : !Arguments ------------------------------------
      74              : ! Scalars
      75              :  integer,intent(in)     :: nband_k,ndat,npw,cplex_fock,nfftf,n4,n5,n6,ngfft(18)
      76              :  integer,intent(in)     :: natom,nspinor,lmn2_size,usepaw,ieigen,nfgd_max
      77              :  logical,intent(in)     :: optfor,optstr,need_ghc
      78              :  integer,intent(out)    :: ndat_occ
      79              :  type(pawcprj_type),intent(in) :: cprj(natom,nspinor*ndat)
      80              : 
      81              : !Local variables-------------------------------
      82              :  integer :: i,ider,nprojs
      83              :  integer,target :: t_fft(3)
      84              :  integer(kind=c_size_t) :: sum_mem,free_mem,fourdp_smem
      85              : 
      86              : ! *************************************************************************
      87              : 
      88            0 :  ider=0
      89            0 :  if (usepaw==1) then
      90              :    nprojs=0
      91            0 :    do i = 1,natom
      92            0 :      nprojs = nprojs + cprj(i, 1)%nlmn
      93              :    end do
      94              :  end if
      95              : 
      96            0 :  t_fft(1) = ngfft(3);
      97            0 :  t_fft(2) = ngfft(2);
      98            0 :  t_fft(3) = ngfft(1);
      99              : 
     100              : #ifdef HAVE_GPU
     101              :  call gpu_get_max_mem(free_mem)
     102              :  free_mem = 0.85 * free_mem ! Cutting 15% out to be safe
     103              : #endif
     104              : 
     105            0 :  do i=1,nband_k
     106            0 :    if(modulo(nband_k,i)/=0) cycle
     107            0 :    ndat_occ=nband_k/i
     108            0 :    sum_mem = 0
     109              : 
     110              :    ! cwavef
     111            0 :    sum_mem = sum_mem + INT(2,c_size_t)*n4*n5*n6*ndat
     112            0 :    if(need_ghc) then
     113              :      ! ghc
     114            0 :      sum_mem = sum_mem + INT(2,c_size_t)*npw*ndat
     115              :      ! ghc1
     116            0 :      sum_mem = sum_mem + INT(2,c_size_t)*npw*ndat
     117              :      ! ghc2
     118            0 :      sum_mem = sum_mem + INT(2,c_size_t)*npw*ndat
     119              :    end if
     120              : 
     121              :    ! cwavef_r
     122            0 :    sum_mem = sum_mem + INT(2,c_size_t)*n4*n5*n6*ndat
     123              :    ! vlocpsi_r
     124            0 :    sum_mem = sum_mem + INT(cplex_fock,c_size_t)*nfftf*ndat
     125              :    ! work (ompgpu_fourwf internal array)
     126            0 :    sum_mem = sum_mem + INT(2,c_size_t)*n4*n5*n6*ndat*ndat_occ
     127              : #ifdef HAVE_GPU
     128              :    call gpu_fft_get_estimate_work_size(3, c_loc(t_fft), FFT_Z2Z, ndat*ndat_occ, fourdp_smem);
     129              : #endif
     130            0 :    sum_mem = sum_mem + fourdp_smem
     131              : 
     132              :    ! rhor_munu
     133            0 :    sum_mem = sum_mem + INT(cplex_fock,c_size_t)*nfftf*ndat_occ*ndat
     134              :    ! rhog_munu
     135            0 :    sum_mem = sum_mem + INT(2,c_size_t)*nfftf*ndat_occ*ndat
     136              :    ! vfock
     137            0 :    sum_mem = sum_mem + INT(cplex_fock,c_size_t)*nfftf*ndat_occ*ndat
     138              :    ! occ
     139            0 :    sum_mem = sum_mem + INT(ndat_occ,c_size_t)
     140              : 
     141              :   !*Additional arrays in case of paw
     142            0 :    if (usepaw==1) then
     143            0 :      if ((optfor).and.(ieigen/=0)) then
     144            0 :        ider=3
     145              :        ! forout
     146            0 :        sum_mem = sum_mem + INT(2,c_size_t)*npw*nspinor*ndat_occ*ndat
     147              : 
     148              :        ! dprojs (gemm_nonlop_ompgpu internal work array)
     149            0 :        sum_mem = sum_mem + INT(2,c_size_t)*nprojs*npw*3
     150              :      end if
     151              : 
     152            0 :      if (optstr.and.(ieigen/=0)) then
     153            0 :        ider=3
     154              :        ! strout
     155            0 :        sum_mem = sum_mem + INT(2,c_size_t)*npw*nspinor*ndat_occ*ndat
     156              : 
     157              :        ! dprojs (gemm_nonlop_ompgpu internal work array)
     158            0 :        sum_mem = sum_mem + INT(2,c_size_t)*nprojs*npw*6
     159              :      end if
     160              :      ! grnhat_12
     161            0 :      ider=ider*2 ! Overestimate this buffer to ensure it fits as we don't manage OpenMP pool of GPU memory
     162            0 :      sum_mem = sum_mem + INT(2,c_size_t)*nfgd_max*nspinor**2*3*natom*(ider/3)*ndat_occ*ndat
     163              :      ! gvnlxc
     164            0 :      sum_mem = sum_mem + INT(2,c_size_t)*npw*nspinor*ndat_occ*ndat
     165              :      ! rho12 (=nhat12 output of pawmknhat_psipsi_ndat)
     166            0 :      sum_mem = sum_mem + INT(2,c_size_t)*nfgd_max*nspinor**2*ndat_occ*ndat*natom
     167              :      ! cprj1 (paw_psipsi internal work array)
     168            0 :      sum_mem = sum_mem + INT(2,c_size_t)*nprojs*nspinor*ndat
     169              :      ! cprj2 (paw_psipsi internal work array)
     170            0 :      sum_mem = sum_mem + INT(2,c_size_t)*nprojs*nspinor*ndat
     171              :      ! cpf  (paw_psipsi internal work array)
     172            0 :      sum_mem = sum_mem + INT(2,c_size_t)*lmn2_size*nspinor*ndat*ndat_occ*natom
     173              : 
     174              :      ! dijhat
     175            0 :      sum_mem = sum_mem + INT(2,c_size_t)*lmn2_size*nspinor*ndat*ndat_occ*natom
     176              : 
     177              :      ! projs (gemm_nonlop_ompgpu internal work array)
     178            0 :      sum_mem = sum_mem + INT(2,c_size_t)*nprojs*npw
     179              :    end if
     180              : 
     181              :    ! cwaveocc_r
     182            0 :    sum_mem = sum_mem + INT(2,c_size_t)*n4*n5*n6*ndat_occ
     183              : 
     184            0 :    sum_mem = sum_mem*dp
     185              : 
     186            0 :    if(sum_mem < free_mem) exit
     187              :  end do
     188              : 
     189            0 :  if(sum_mem > free_mem) then
     190            0 :    ABI_WARNING("Test case doesn't fit in GPU memory. Try to lower bandpp.")
     191              :  end if
     192              : !#ifdef DEBUG_VERBOSE
     193            0 :  write(std_out,*) "-----------DEBUG fock_getghc%select_ndat_occ_for_gpu : "
     194            0 :  write(std_out,'(A,F10.3,1x,A)') "Considered free GPU memory     : ", real(free_mem,dp)/(1024*1024), "MiB"
     195            0 :  write(std_out,'(A,I4)')         "selected ndat_occ              : ", ndat_occ
     196            0 :  write(std_out,'(A,F10.3,1x,A)') "Forecasted consumed GPU memory : ", real(sum_mem,dp)/(1024*1024), "MiB"
     197            0 :  write(std_out,*) "-----------END DEBUG fock_getghc%select_ndat_occ_for_gpu : "
     198              : !#endif
     199              : 
     200            0 :  end subroutine select_ndat_occ_for_gpu
     201              : 
     202              : !!****f* ABINIT/fock_getghc
     203              : !! NAME
     204              : !!  fock_getghc
     205              : !!
     206              : !! FUNCTION
     207              : !!  Compute the matrix elements <G|Vx|psi> of the Fock operator.
     208              : !!
     209              : !! INPUTS
     210              : !!  cwavef(2,npw*nspinor*ndat)= planewave coefficients of wavefunctions on which Fock operator is applied.
     211              : !!  cwaveprj <type(pawcprj_type> = <cwavevf|proj>
     212              : !!  gs_ham <type(gs_hamiltonian_type)>=all data for the Hamiltonian to be applied
     213              : !!  mpi_enreg= information about MPI parallelization
     214              : !!
     215              : !! SIDE EFFECTS
     216              : !!  ghc(2,npw*ndat)= matrix elements <G|H|C> or <G|H-lambda.S|C> (if sij_opt>=0 or =-1 in getghc)
     217              : !!                   contains the fock exchange term for cwavef at the end.
     218              : !!
     219              : !! NOTES
     220              : !!  The current version assumes that:
     221              : !!   * nspinor = 1
     222              : !!   * no "my_nspinor"
     223              : !!   * no restriction to the value of istwfk_bz (but must be tested in all case)
     224              : !!   * all the data for the occupied states (cgocc_bz) are the same as those for the current states (cg)
     225              : !!
     226              : !! SOURCE
     227              : 
     228        29003 : subroutine fock_getghc(cwavef,cwaveprj,ghc,gs_ham,mpi_enreg,ndat)
     229              : 
     230              : !Arguments ------------------------------------
     231              : ! Scalars
     232              :  integer,intent(in)     :: ndat
     233              :  type(MPI_type),intent(in) :: mpi_enreg
     234              :  type(gs_hamiltonian_type),target,intent(inout) :: gs_ham
     235              : ! Arrays
     236              :  type(pawcprj_type),intent(inout) :: cwaveprj(:,:)
     237              :  real(dp),intent(inout) :: cwavef(:,:)!,ghc(2,gs_ham%npw_k)
     238              :  real(dp),intent(inout) :: ghc(:,:)
     239              : 
     240              : !Local variables-------------------------------
     241              : ! Scalars
     242              :  integer,parameter :: tim_fourwf_fock_getghc=10,tim_fourdp_fock_getghc=10
     243              :  integer :: bdtot_jindex,choice,cplex_fock,cplex_dij,cpopt,i1,i2,i3,ia,iatom,idat,idat_occ,idat_tot,iatm
     244              :  integer :: iband_cprj,ider,idir,idir1,ier,ii,ind,ipw,ieigen,ifft,itypat,izero,jband,jbg,jcg,jkg
     245              :  integer :: jkpt,my_jsppol,jstwfk,lmn2_size,mgfftf,mpw,n1,n2,n3,n4,n5,n6,ndat_occ,ndat_tot
     246              :  integer :: n1f,n2f,n3f,n4f,n5f,n6f,natom,nband_k,ndij,nfft,nfftf,nfftotf,nhat12_grdim,nnlout
     247              :  integer :: nfgd_max
     248              :  integer :: npw,npwj,nspden_fock,nspinor,nkpg,paw_opt,signs,tim_nonlop,gpu_option
     249              :  integer, save :: ncount=0
     250              :  logical :: need_ghc,qeq0
     251              :  real(dp),parameter :: weight1=one
     252              :  real(dp) :: doti,eigen,imcwf,imcwocc,imvloc,invucvol,recwf,recwocc,revloc,wtk,esum,esumi
     253              :  complex(dp) :: cinvucvol,cucvol
     254              :  type(fock_common_type),pointer :: fockcommon
     255              :  type(fock_BZ_type),pointer :: fockbz
     256              : ! Arrays
     257              :  integer :: ngfft(18),ngfftf(18)
     258        29003 :  integer,pointer :: gboundf(:,:),kg_occ(:,:),gbound_kp(:,:)
     259              :  real(dp) :: fockstr(6),qphon(3),qvec_j(3),tsec(2),gsc_dum(2,0),rhodum(2,1)
     260              :  real(dp) :: rhodum0(0,1,1)
     261        29003 :  real(dp), allocatable :: dummytab(:,:),dijhat(:,:,:,:,:),dijhat_tmp(:,:,:),ffnl_kp_dum(:,:,:,:),kpg_kp(:,:),occ(:)
     262        29003 :  real(dp), allocatable, target :: gvnlxc(:,:),ghc1(:,:),ghc2(:,:),grnhat12(:,:,:,:,:,:),grnhat_12(:,:,:,:,:,:,:),forikpt(:,:,:)
     263        29003 :  real(dp), allocatable :: rho12(:,:,:,:,:,:),rhog_munu(:,:,:,:),rhor_munu(:,:,:,:),vlocpsi_r(:,:),strdat(:,:,:,:)
     264        29003 :  real(dp), allocatable :: vfock(:,:,:),psilocal(:,:,:),enlout_dum(:),vectin_dum(:,:),vqg(:),forout(:,:),strout(:,:),for1(:,:,:,:)
     265        29003 :  real(dp), allocatable,target ::cwavef_r(:,:,:,:),cwavef_rep(:,:),vdotr(:,:,:,:),vdoti(:),vfockstr(:,:,:)
     266        29003 :  real(dp), ABI_CONTIGUOUS  pointer :: cwaveocc_r(:,:,:,:,:)
     267        29003 :  type(pawcprj_type),pointer :: cwaveocc_prj(:,:)
     268        29003 :  type(pawcprj_type),pointer :: cwaveocc_prj_rep(:,:)
     269              : 
     270              :  real(dp) :: rprimd(3,3),for12(3)
     271        29003 :  integer,  ABI_CONTIGUOUS pointer :: atom_ifftsph(:,:),atom_nfgd(:)
     272        29003 :  real(dp), ABI_CONTIGUOUS pointer :: stress_ikpt(:,:),atom_rfgd(:,:,:)
     273              : 
     274              : 
     275              : ! *************************************************************************
     276              : !return
     277              : 
     278        29003 :  ncount=ncount+1
     279              : 
     280        29003 :  call timab(1504,1,tsec) ; call timab(1505,-1,tsec) ; call timab(1515,-1,tsec) ; call timab(1541,-1,tsec)
     281              : 
     282        29003 :  ABI_CHECK(associated(gs_ham%fockcommon),"fock_common must be associated!")
     283        29003 :  fockcommon => gs_ham%fockcommon
     284        29003 :  ABI_CHECK(associated(gs_ham%fockbz),"fock_bz must be associated!")
     285        29003 :  fockbz => gs_ham%fockbz
     286              : 
     287        29003 :  ABI_CHECK(gs_ham%nspinor==1,"only allowed for nspinor=1!")
     288        29003 :  ABI_CHECK(gs_ham%npw_k==gs_ham%npw_kp,"only allowed for npw_k=npw_kp (ground state)!")
     289        29003 :  if (fockcommon%usepaw==1) then
     290         2061 :    ABI_CHECK((size(cwaveprj,1)==gs_ham%natom.and.size(cwaveprj,2)==gs_ham%nspinor*ndat),"error on cwaveprj dims")
     291              :  end if
     292        29003 :  need_ghc=(size(ghc,2)>0)
     293              : 
     294              : !Some constants
     295        29003 :  invucvol=1.d0/sqrt(gs_ham%ucvol)
     296        29003 :  cinvucvol=dcmplx(invucvol,0.0_dp)
     297        29003 :  cucvol=dcmplx(sqrt(gs_ham%ucvol),0.0_dp)
     298        29003 :  call matr3inv(gs_ham%gprimd,rprimd)
     299        29003 :  cplex_fock=2;nspden_fock=1
     300        29003 :  natom=fockcommon%natom
     301        29003 :  nspinor=gs_ham%nspinor
     302              :  mpw=maxval(fockbz%npwarr)
     303        29003 :  npw=gs_ham%npw_k
     304        29003 :  gpu_option=gs_ham%gpu_option
     305        29003 :  ider=0;izero=0
     306        29003 :  if (fockcommon%usepaw==1) then
     307        39159 :    nfft =fockcommon%pawfgr%nfftc ; ngfft =fockcommon%pawfgr%ngfftc
     308        39159 :    nfftf=fockcommon%pawfgr%nfft  ; ngfftf=fockcommon%pawfgr%ngfft
     309         2061 :    mgfftf=fockcommon%pawfgr%mgfft
     310              :  else
     311        26942 :    nfft =gs_ham%nfft  ; nfftf =nfft
     312       511898 :    ngfft=gs_ham%ngfft ; ngfftf=ngfft
     313        26942 :    mgfftf=gs_ham%mgfft
     314              :  end if
     315        29003 :  n1=ngfft(1);n2=ngfft(2);n3=ngfft(3)
     316        29003 :  n4=ngfft(4);n5=ngfft(5);n6=ngfft(6)
     317        29003 :  n1f=ngfftf(1);n2f=ngfftf(2);n3f=ngfftf(3)
     318        29003 :  n4f=ngfftf(4);n5f=ngfftf(5);n6f=ngfftf(6)
     319              : 
     320              : !*Max number of fine-grid points in a PAW augmentation sphere (over all atoms).
     321              : !*Used to size the small per-atom rho12/grnhat_12 sphere buffers instead of the full FFT grid.
     322        29003 :  nfgd_max=1
     323        29003 :  if (fockcommon%usepaw==1) then
     324         6183 :    nfgd_max=max(1,maxval(fockcommon%pawfgrtab(1:natom)%nfgd))
     325              :  end if
     326              : 
     327              : ! ===========================
     328              : ! === Initialize arrays   ===
     329              : ! ===========================
     330              : ! transient optfor and optstress
     331              : ! fockcommon%optfor=.false.
     332              : ! fockcommon%optstr=.false.
     333              : !*Initialization of local pointers
     334              : !*Initialization of the array cwavef_r
     335              : !*cwavef_r = current wavefunction in r-space
     336       145015 :  ABI_MALLOC(cwavef_r,(2,n4f,n5f,n6f*ndat))
     337              : #ifdef HAVE_OPENMP_OFFLOAD
     338              :  !$OMP TARGET ENTER DATA MAP(alloc:cwavef_r) IF(gpu_option==ABI_GPU_OPENMP)
     339              : #endif
     340              : !*dummytab = variables for fourwf
     341        87009 :  ABI_MALLOC(dummytab,(2,nfft*ndat))
     342              : !*vqg = 4pi/(G+q)**2
     343        87009 :  ABI_MALLOC(vqg,(nfftf))
     344              : 
     345        29003 :  if(need_ghc) then
     346              :   !*Initialization of the array ghc1
     347              :   !*ghc1 will contain the exact exchange contribution to the Hamiltonian
     348        80853 :    ABI_MALLOC(ghc1,(2,npw*ndat))
     349        53902 :    ABI_MALLOC(ghc2,(2,npw*ndat))
     350              : #ifdef HAVE_OPENMP_OFFLOAD
     351              :    !$OMP TARGET ENTER DATA MAP(alloc:ghc1,ghc2,vqg) IF(gpu_option==ABI_GPU_OPENMP)
     352              : #endif
     353        26951 :    if(gpu_option==ABI_GPU_DISABLED) then
     354     20048969 :      ghc1=zero
     355     20048969 :      ghc2=zero
     356            0 :    else if(gpu_option==ABI_GPU_OPENMP) then
     357            0 :      call gpu_set_to_zero(ghc1, int(2,c_size_t)*npw*ndat)
     358            0 :      call gpu_set_to_zero(ghc2, int(2,c_size_t)*npw*ndat)
     359              :    end if
     360              :  end if
     361              : !*Initialization of the array vlocpsi_r
     362              : !*vlocpsi_r = partial local Fock operator applied to cwavef in r-space and summed over all occupied (jkpt,mu)
     363       116012 :  ABI_MALLOC(vlocpsi_r,(cplex_fock*nfftf,ndat))
     364              : #ifdef HAVE_OPENMP_OFFLOAD
     365              :  !$OMP TARGET ENTER DATA MAP(alloc:vlocpsi_r) IF(gpu_option==ABI_GPU_OPENMP)
     366              : #endif
     367        29003 :  if(gpu_option==ABI_GPU_DISABLED) then
     368    456957546 :    vlocpsi_r=zero
     369            0 :  else if(gpu_option==ABI_GPU_OPENMP) then
     370            0 :    call gpu_set_to_zero(vlocpsi_r, int(cplex_fock,c_size_t)*nfftf*ndat)
     371              :  end if
     372              : 
     373              : !*Additional arrays in case of paw
     374        29003 :  if (fockcommon%usepaw==1) then
     375         2061 :    nhat12_grdim=0
     376              :  end if
     377              : 
     378        29003 :  if (fockcommon%usepaw==1) then
     379         2061 :    if ((fockcommon%optfor).and.(fockcommon%ieigen/=0)) then
     380         4208 :      ABI_MALLOC(forikpt,(3,natom,ndat))
     381        10520 :      forikpt=zero
     382              :    end if
     383              :  end if
     384        29003 :  if (fockcommon%usepaw==1.or.fockcommon%optstr) then
     385        15596 :    ABI_MALLOC(gboundf,(2*mgfftf+8,2))
     386         3899 :    call sphereboundary(gboundf,gs_ham%istwf_k,gs_ham%kg_k,mgfftf,npw)
     387              :  else
     388        25104 :    gboundf=>gs_ham%gbound_k
     389              :  end if
     390              : ! ==========================================
     391              : ! === Get cwavef in real space using FFT ===
     392              : ! ==========================================
     393        29003 :  if(gpu_option==ABI_GPU_DISABLED) then
     394    740383784 :    cwavef_r=zero
     395            0 :  else if(gpu_option==ABI_GPU_OPENMP) then
     396            0 :    call gpu_set_to_zero(cwavef_r, int(2,c_size_t)*n4f*n5f*n6f*ndat)
     397              :  end if
     398        29003 :  call timab(1515,2,tsec) ; call timab(1541,-2,tsec) ; call timab(1512,-1,tsec)
     399              :  call fourwf(0,rhodum0,cwavef,rhodum,cwavef_r,gboundf,gboundf,gs_ham%istwf_k,gs_ham%kg_k,gs_ham%kg_k,&
     400              : & mgfftf,mpi_enreg,ndat,ngfftf,npw,1,n4f,n5f,n6f,0,tim_fourwf_fock_getghc,weight1,weight1,&
     401        29003 : & gpu_option=gs_ham%gpu_option)
     402        29003 :  call timab(1512,2,tsec) ; call timab(1515,-1,tsec) ; call timab(1541,-1,tsec)
     403        29003 :  if(gpu_option==ABI_GPU_DISABLED) then
     404    740383784 :    cwavef_r=cwavef_r*invucvol
     405            0 :  else if(gpu_option==ABI_GPU_OPENMP) then
     406            0 :    call abi_xscal(n4f*n5f*n6f*ndat,cinvucvol,cwavef_r,1,x_cplx=2,gpu_option=gpu_option)
     407              :  end if
     408              : 
     409              : ! =====================================================
     410              : ! === Select the states in cgocc_bz with the same spin ===
     411              : ! =====================================================
     412              : !* Initialization of the indices/shifts, according to the value of isppol
     413              : !* bdtot_jindex = shift to be applied on the location of data in the array occ_bz ?
     414        29003 :  bdtot_jindex=0
     415              : !* jbg = shift to be applied on the location of data in the array cprj/occ
     416        29003 :  jbg=0;jcg=0
     417        29003 :  my_jsppol=fockcommon%isppol
     418        29003 :  if((fockcommon%isppol==2).and.(mpi_enreg%nproc_spkpt/=1)) my_jsppol=1
     419              : 
     420              : !===================================
     421              : !=== Loop on the k-points in IBZ ===
     422              : !===================================
     423        29003 :  jkg=0
     424              : 
     425        29003 :  if (associated(gs_ham%ph3d_kp)) then
     426        29003 :    nullify (gs_ham%ph3d_kp)
     427              :  end if
     428              : 
     429        29003 :  call timab(1505,2,tsec) ; call timab(1506,-1,tsec) ; call timab(1541,-2,tsec)
     430              : 
     431       231529 :  do jkpt=1,fockbz%mkpt
     432              : 
     433       202526 :    if(fockbz%nbandocc_bz(jkpt,my_jsppol)==0) cycle
     434              : 
     435       202526 :    call timab(1521,1,tsec)
     436              : 
     437              : !* nband_k = number of bands at point k_j
     438       202526 :    nband_k=fockbz%nbandocc_bz(jkpt,my_jsppol)
     439              : 
     440              :    ! Select ndat_occ value :
     441              :    ! GPU : check GPU memory available and compute maximum value for ndat_occ
     442              :    ! CPU : 4, because it seems to be optimal from my observations
     443       202526 :    if(gpu_option/=ABI_GPU_DISABLED) then
     444            0 :      lmn2_size=0
     445            0 :      if(fockcommon%usepaw==1) lmn2_size=fockcommon%pawtab(1)%lmn2_size
     446              :      call select_ndat_occ_for_gpu(ndat_occ,nband_k,ndat,npw,cplex_fock,&
     447              : &        nfftf,ngfftf,n4f,n5f,n6f,natom,nspinor,lmn2_size,&
     448            0 : &        fockcommon%usepaw,cwaveprj,fockcommon%ieigen,need_ghc,fockcommon%optfor,fockcommon%optstr,nfgd_max)
     449              :    else
     450       202526 :      ndat_occ=min(nband_k,16)
     451       202526 :      do ii=1,nband_k
     452       202526 :        if(modulo(nband_k,ndat_occ)==0) exit
     453       202526 :        ndat_occ=ndat_occ-1
     454              :      end do
     455              :    end if
     456              : !* ndat_tot = combined batch size (ndat*ndat_occ), used to batch nonlop calls
     457       202526 :    ndat_tot=ndat*ndat_occ
     458              : 
     459              : !* wtk = weight in BZ of this k point
     460       202526 :    wtk=fockbz%wtk_bz(jkpt) !*sqrt(gs_ham%ucvol)
     461              : !* jstwfk= how is stored the wavefunction
     462       202526 :    jstwfk=fockbz%istwfk_bz(jkpt)
     463              : !* npwj= number of plane wave in basis for the wavefunction
     464       202526 :    npwj=fockbz%npwarr(jkpt)
     465              : !* Basis sphere of G vectors
     466       202526 :    if (allocated(fockbz%cgocc)) then
     467       202526 :      gbound_kp => fockbz%gbound_bz(:,:,jkpt)
     468       202526 :      kg_occ => fockbz%kg_bz(:,1+jkg:npwj+jkg)
     469              :    end if
     470              : 
     471              :   !*rhormunu = overlap matrix between cwavef and (jkpt,mu) in R-space
     472      1215156 :    ABI_MALLOC(rhor_munu,(cplex_fock,nfftf,ndat_occ,ndat))
     473              : #ifdef HAVE_OPENMP_OFFLOAD
     474              :    !$OMP TARGET ENTER DATA MAP(alloc:rhor_munu) IF(gpu_option==ABI_GPU_OPENMP)
     475              : #endif
     476              :   !*rhogmunu = overlap matrix between cwavef and (jkpt,mu) in G-space
     477      1012630 :    ABI_MALLOC(rhog_munu,(2,nfftf,ndat_occ,ndat))
     478              : #ifdef HAVE_OPENMP_OFFLOAD
     479              :    !$OMP TARGET ENTER DATA MAP(alloc:rhog_munu) IF(gpu_option==ABI_GPU_OPENMP)
     480              : #endif
     481              :   !*vfock = Fock potential
     482      1012630 :    ABI_MALLOC(vfock,(cplex_fock*nfftf,ndat_occ,ndat))
     483              : #ifdef HAVE_OPENMP_OFFLOAD
     484              :    !$OMP TARGET ENTER DATA MAP(alloc:vfock) IF(gpu_option==ABI_GPU_OPENMP)
     485              : #endif
     486       607578 :    ABI_MALLOC(occ,(ndat_occ))
     487              : #ifdef HAVE_OPENMP_OFFLOAD
     488              :    !$OMP TARGET ENTER DATA MAP(alloc:occ) IF(gpu_option==ABI_GPU_OPENMP)
     489              : #endif
     490              : 
     491              :   !*Additional arrays in case of paw
     492       202526 :    if (fockcommon%usepaw==1) then
     493         9678 :      if ((fockcommon%optfor).and.(fockcommon%ieigen/=0)) then
     494         2804 :        ider=3
     495         8412 :        ABI_MALLOC(forout,(2,npw*nspinor*ndat_tot))
     496              : #ifdef HAVE_OPENMP_OFFLOAD
     497              :        !$OMP TARGET ENTER DATA MAP(alloc:forout) IF(gpu_option==ABI_GPU_OPENMP)
     498              : #endif
     499              :      end if
     500              : 
     501         9678 :      if (fockcommon%optstr.and.(fockcommon%ieigen/=0)) then
     502         1870 :        ider=3
     503         5610 :        ABI_MALLOC(strout,(2,npw*nspinor*ndat_tot))
     504              : #ifdef HAVE_OPENMP_OFFLOAD
     505              :        !$OMP TARGET ENTER DATA MAP(alloc:strout) IF(gpu_option==ABI_GPU_OPENMP)
     506              : #endif
     507              :      end if
     508        77424 :      ABI_MALLOC(grnhat_12,(2,nfgd_max,nspinor**2,3,natom*(ider/3),ndat_occ,ndat))
     509        29034 :      ABI_MALLOC(gvnlxc,(2,npw*nspinor*ndat_tot))
     510         9678 :      ABI_MALLOC(grnhat12,(1,1,1,1,1,1))
     511        67746 :      ABI_MALLOC(rho12,(2,nfgd_max,nspinor**2,ndat_occ,ndat,natom))
     512              : 
     513        29034 :      ABI_MALLOC(atom_nfgd,    (natom))
     514        29034 :      do iatom=1,natom
     515        29034 :        atom_nfgd(iatom) = fockcommon%pawfgrtab(iatom)%nfgd
     516              :      end do
     517        38712 :      ABI_MALLOC(atom_ifftsph, (nfgd_max, natom))
     518        38712 :      ABI_MALLOC(atom_rfgd,    (3, nfgd_max, natom))
     519        29034 :      do iatom=1,natom
     520     15460232 :        atom_ifftsph(1:atom_nfgd(iatom),iatom) = fockcommon%pawfgrtab(iatom)%ifftsph(1:atom_nfgd(iatom))
     521     61792538 :        atom_rfgd(:,1:atom_nfgd(iatom),iatom) =  fockcommon%pawfgrtab(iatom)%rfgd(:,1:atom_nfgd(iatom))
     522              :      end do
     523              : 
     524              : #ifdef HAVE_OPENMP_OFFLOAD
     525              :      !$OMP TARGET ENTER DATA MAP(alloc:grnhat_12) IF(gpu_option==ABI_GPU_OPENMP .and. ider==3)
     526              :      !$OMP TARGET ENTER DATA MAP(alloc:gvnlxc) IF(gpu_option==ABI_GPU_OPENMP)
     527              :      !$OMP TARGET ENTER DATA MAP(alloc:rho12) IF(gpu_option==ABI_GPU_OPENMP)
     528              :      !$OMP TARGET ENTER DATA MAP(alloc:atom_ifftsph,atom_nfgd,atom_rfgd) IF(gpu_option==ABI_GPU_OPENMP)
     529              :      !$OMP TARGET UPDATE TO(atom_ifftsph,atom_nfgd,atom_rfgd) IF(gpu_option==ABI_GPU_OPENMP)
     530              : #endif
     531              :    end if
     532              : 
     533              : !* Load k^prime hamiltonian in the gs_ham datastructure
     534              : !  Note: ffnl_kp / ph3d_kp / gbound_kp are not used
     535              : 
     536       202526 :    if (.not. associated(gs_ham%ph3d_kp)) then
     537       810104 :      ABI_MALLOC(gs_ham%ph3d_kp,(2,npwj,gs_ham%matblk))
     538              :    end if
     539              : 
     540              :    call gs_ham%load_kprime(kpt_kp=fockbz%kptns_bz(:,jkpt),&
     541       202526 : &   istwf_kp=jstwfk,npw_kp=npwj,kg_kp=fockbz%kg_bz(:,1+jkg:npwj+jkg))
     542              : !* Some temporary allocations needed for PAW
     543       202526 :    if (fockcommon%usepaw==1) then
     544        29034 :      ABI_MALLOC(enlout_dum,(ndat_tot))
     545        29034 :      ABI_MALLOC(vectin_dum,(2,npwj*nspinor*ndat_tot))
     546     28480275 :      vectin_dum=zero
     547        48390 :      ABI_MALLOC(ffnl_kp_dum,(npwj,1,gs_ham%lmnmax,gs_ham%ntypat))
     548         9678 :      nkpg=size(gs_ham%kpg_k,2)
     549        38712 :      ABI_MALLOC(kpg_kp,(npwj,nkpg))
     550         9678 :      if (nkpg>0) then
     551         9678 :        call mkkpg(gs_ham%kg_kp,kpg_kp,gs_ham%kpt_kp,nkpg,npwj)
     552              :      end if
     553         9678 :      call gs_ham%load_kprime(ffnl_kp=ffnl_kp_dum,kpg_kp=kpg_kp)
     554              :    end if
     555              : 
     556              : ! ======================================
     557              : ! === Calculate the vector q=k_i-k_j ===
     558              : ! ======================================
     559              : !* Evaluation of kpoint_j, the considered k-point in reduced coordinates
     560              : !     kpoint_j(:)=fockbz%kptns_bz(:,jkpt)
     561              : !* the vector qvec is expressed in reduced coordinates.
     562              : !     qvec(:)=kpoint_i(:)-kpoint_j(:)
     563       810104 :    qvec_j(:)=gs_ham%kpt_k(:)-fockbz%kptns_bz(:,jkpt)
     564       202526 :    qeq0=(qvec_j(1)**2+qvec_j(2)**2+qvec_j(3)**2<1.d-15)
     565              : 
     566              :    ! Get the Coulomb interaction in reciprocal space
     567       202526 :    call bare_vqg(qvec_j,fockcommon,gs_ham%gmet,nfftf,fockbz%nkpt_bz,ngfftf,gs_ham%ucvol,vqg)
     568              : #ifdef HAVE_OPENMP_OFFLOAD
     569              :    !$OMP TARGET UPDATE TO(vqg) IF(gpu_option==ABI_GPU_OPENMP)
     570              : #endif
     571              : 
     572       202526 :    call timab(1521,2,tsec)
     573              : 
     574              : ! =================================================
     575              : ! === Loop on the band indices jband of cgocc_k ===
     576              : ! =================================================
     577       405052 :    do jband=1,nband_k,ndat_occ
     578              : 
     579              : !*   occ = occupancy of jband at this k point
     580      1115372 :      occ(1:ndat_occ)=fockbz%occ_bz(jband+bdtot_jindex:jband+ndat_occ-1+bdtot_jindex,my_jsppol)
     581      1317898 :      if(maxval(occ(1:ndat_occ))<tol8) cycle
     582              : #ifdef HAVE_OPENMP_OFFLOAD
     583              :      !$OMP TARGET UPDATE TO(occ) IF(gpu_option==ABI_GPU_OPENMP)
     584              : #endif
     585              : 
     586              : !    This timing is placed after the cycle ...
     587       202526 :      call timab(1522,1,tsec) ; call timab(1542,-1,tsec)
     588              : 
     589              : ! ==============================================
     590              : ! === Get cwaveocc_r in real space using FFT ===
     591              : ! ==============================================
     592       202526 :      if (allocated(fockbz%cwaveocc_bz)) then
     593            0 :        cwaveocc_r => fockbz%cwaveocc_bz(:,:,:,:,jband+jbg:jband+jbg+ndat_occ-1,my_jsppol)
     594              :      else
     595      1215156 :        ABI_MALLOC(cwaveocc_r,(2,n4f,n5f,n6f,ndat_occ))
     596              : #ifdef HAVE_OPENMP_OFFLOAD
     597              :        !$OMP TARGET ENTER DATA MAP(alloc:cwaveocc_r) IF(gpu_option==ABI_GPU_OPENMP)
     598              : #endif
     599       202526 :        if(gpu_option==ABI_GPU_DISABLED) then
     600  13556461613 :          cwaveocc_r=zero
     601            0 :        else if(gpu_option==ABI_GPU_OPENMP) then
     602            0 :          call gpu_set_to_zero(cwaveocc_r, int(2,c_size_t)*n4f*n5f*n6f*ndat_occ)
     603              :        end if
     604       202526 :        call timab(1515,2,tsec) ; call timab(1512,-1,tsec) ; call timab(1542,-2,tsec)
     605              :        call fourwf(1,rhodum0,fockbz%cgocc(:,1+jcg+npwj*(jband-1):jcg+(jband+ndat_occ-1)*npwj,my_jsppol),rhodum,cwaveocc_r, &
     606              : &       gbound_kp,gbound_kp,jstwfk,kg_occ,kg_occ,mgfftf,mpi_enreg,ndat_occ,ngfftf,&
     607       202526 : &       npwj,1,n4f,n5f,n6f,0,tim_fourwf_fock_getghc,weight1,weight1,gpu_option=gs_ham%gpu_option)
     608       202526 :        call timab(1512,2,tsec) ; call timab(1515,-1,tsec) ; call timab(1542,-1,tsec)
     609       202526 :        if(gpu_option==ABI_GPU_DISABLED) then
     610  13556461613 :          cwaveocc_r=cwaveocc_r*invucvol
     611            0 :        else if(gpu_option==ABI_GPU_OPENMP) then
     612            0 :          call abi_xscal(n4f*n5f*n6f*ndat_occ,cinvucvol,cwaveocc_r,1,x_cplx=2,gpu_option=gpu_option)
     613              :        end if
     614              :      end if
     615              : 
     616              : ! ================================================
     617              : ! === Get the overlap density matrix rhor_munu ===
     618              : ! ================================================
     619              : !* Calculate the overlap density matrix in real space = conj(cwaveocc_r)*cwavef_r
     620              : !* rhor_munu will contain the overlap density matrix.
     621              : ! vfock=-int{conj(cwaveocc_r)*cwavef_r*dr'/|r-r'|}
     622              : 
     623       202526 :      call timab(1522,2,tsec) ; call timab(1542,-2,tsec) ; call timab(1523,-1,tsec)
     624              : 
     625       202526 :      if(gpu_option==ABI_GPU_DISABLED) then
     626              :        !$OMP PARALLEL DO COLLAPSE(2) &
     627              :        !$OMP& PRIVATE(ind,imcwf,recwf,recwocc,imcwocc)
     628       405052 :        do idat=1,ndat
     629      1317898 :        do idat_occ=1,ndat_occ
     630     15580767 :          do i3=1,n3f
     631    251108924 :            do i2=1,n2f
     632   4349064708 :              do i1=1,n1f
     633   4098868630 :                ind=i1+(i2-1)*n1f+(i3-1)*n2f*n1f
     634   4098868630 :                recwf  =cwavef_r(1,i1,i2,(idat-1)*n3f+i3)
     635   4098868630 :                imcwf  =cwavef_r(2,i1,i2,(idat-1)*n3f+i3)
     636   4098868630 :                recwocc=cwaveocc_r(1,i1,i2,i3,idat_occ)
     637   4098868630 :                imcwocc=cwaveocc_r(2,i1,i2,i3,idat_occ)
     638   4098868630 :                rhor_munu(1,ind,idat_occ,idat)= recwocc*recwf+imcwocc*imcwf
     639   4334599313 :                rhor_munu(2,ind,idat_occ,idat)= recwocc*imcwf-imcwocc*recwf
     640              :              end do ! i1
     641              :            end do ! i2
     642              :          end do ! i3
     643              :        end do ! idat_occ
     644              :        end do ! idat
     645              :      else if(gpu_option==ABI_GPU_OPENMP) then
     646              : #ifdef HAVE_OPENMP_OFFLOAD
     647              :        !$OMP TARGET TEAMS DISTRIBUTE COLLAPSE(2) &
     648              :        !$OMP& MAP(to:rhor_munu,cwavef_r,cwaveocc_r) PRIVATE(idat,idat_occ)
     649              :        do idat=1,ndat
     650              :        do idat_occ=1,ndat_occ
     651              :          !$OMP PARALLEL DO COLLAPSE(3) PRIVATE(ind,i3,i2,i1)
     652              :          do i3=1,n3f
     653              :            do i2=1,n2f
     654              :              do i1=1,n1f
     655              :                ind=i1+(i2-1)*n1f+(i3-1)*n2f*n1f
     656              :                rhor_munu(1,ind,idat_occ,idat)= cwaveocc_r(1,i1,i2,i3,idat_occ)*cwavef_r(1,i1,i2,(idat-1)*n3f+i3)&
     657              :                                               +cwaveocc_r(2,i1,i2,i3,idat_occ)*cwavef_r(2,i1,i2,(idat-1)*n3f+i3)
     658              :                rhor_munu(2,ind,idat_occ,idat)= cwaveocc_r(1,i1,i2,i3,idat_occ)*cwavef_r(2,i1,i2,(idat-1)*n3f+i3)&
     659              :                                               -cwaveocc_r(2,i1,i2,i3,idat_occ)*cwavef_r(1,i1,i2,(idat-1)*n3f+i3)
     660              :              end do ! i1
     661              :            end do ! i2
     662              :          end do ! i3
     663              :        end do ! idat_occ
     664              :        end do ! idat
     665              : #endif
     666              :      end if ! gpu_option
     667              : 
     668       202526 :      call timab(1523,2,tsec)
     669              : 
     670              : ! =======================================================
     671              : ! === Add compensation charge density in the PAW case ===
     672              : ! =======================================================
     673              : 
     674       202526 :      call timab(1524,-1,tsec) ; call timab(1544,-1,tsec)
     675              : 
     676       202526 :      if (fockcommon%usepaw==1) then
     677              : 
     678         9678 :        iband_cprj=(my_jsppol-1)*fockbz%mkptband+jbg+jband
     679         9678 :        cwaveocc_prj=>fockbz%cwaveocc_prj(:,iband_cprj:iband_cprj+ndat_occ*nspinor-1)
     680              : 
     681              :        call pawmknhat_psipsi_ndat(cwaveprj(:,:),cwaveocc_prj(:,:),&
     682              :        &    ider,izero,natom,natom,nfftf,ngfftf,&
     683              :        &    nhat12_grdim,nspinor,fockcommon%ntypat,ndat,ndat_occ,fockbz%pawang,fockcommon%pawfgrtab,grnhat12,&
     684              :        &    rho12,gs_ham%nattyp,&
     685              :        &    fockcommon%pawtab,gprimd=gs_ham%gprimd,grnhat_12=grnhat_12,qphon=qvec_j,&
     686         9678 :        &    xred=gs_ham%xred,atindx=gs_ham%atindx,gpu_option=gpu_option)
     687              : 
     688         9678 :        if(gpu_option==ABI_GPU_DISABLED) then
     689              :          !$OMP PARALLEL DO COLLAPSE(2) &
     690              :          !$OMP& PRIVATE(idat,idat_occ,iatom,ifft,ind)
     691        19356 :          do idat=1,ndat
     692        57729 :            do idat_occ=1,ndat_occ
     693       124797 :              do iatom=1,natom
     694     60932723 :                do ifft=1,atom_nfgd(iatom)
     695     60817604 :                  ind = atom_ifftsph(ifft,iatom)
     696     60817604 :                  rhor_munu(1,ind,idat_occ,idat) = rhor_munu(1,ind,idat_occ,idat) + rho12(1,ifft,nspinor,idat_occ,idat,iatom)
     697     60894350 :                  rhor_munu(2,ind,idat_occ,idat) = rhor_munu(2,ind,idat_occ,idat) - rho12(2,ifft,nspinor,idat_occ,idat,iatom)
     698              :                end do ! ifft
     699              :              end do ! iatom
     700              :            end do ! idat_occ
     701              :          end do ! idat
     702              :        else if(gpu_option==ABI_GPU_OPENMP) then
     703              : #ifdef HAVE_OPENMP_OFFLOAD
     704              :          !$OMP TARGET TEAMS DISTRIBUTE COLLAPSE(2) &
     705              :          !$OMP& MAP(to:rhor_munu,rho12,atom_nfgd,atom_ifftsph) PRIVATE(idat,idat_occ)
     706              :          do idat=1,ndat
     707              :            do idat_occ=1,ndat_occ
     708              :              !$OMP PARALLEL DO PRIVATE(iatom,ifft,ind)
     709              :              do iatom=1,natom
     710              :                do ifft=1,atom_nfgd(iatom)
     711              :                  ind = atom_ifftsph(ifft,iatom)
     712              :                  rhor_munu(1,ind,idat_occ,idat) = rhor_munu(1,ind,idat_occ,idat) + rho12(1,ifft,nspinor,idat_occ,idat,iatom)
     713              :                  rhor_munu(2,ind,idat_occ,idat) = rhor_munu(2,ind,idat_occ,idat) - rho12(2,ifft,nspinor,idat_occ,idat,iatom)
     714              :                end do ! ifft
     715              :              end do ! iatom
     716              :            end do ! idat_occ
     717              :          end do ! idat
     718              : #endif
     719              :        end if
     720              :      end if
     721              : 
     722              : 
     723       202526 :      call timab(1515,2,tsec) ; call timab(1513,-1,tsec) ; call timab(1544,-2,tsec)
     724              :      ! Perform an FFT using fourwf to get rhog_munu = FFT^-1(rhor_munu)
     725              :      call fourdp(cplex_fock,rhog_munu,rhor_munu,-1,mpi_enreg,nfftf,ndat*ndat_occ,&
     726       202526 : &         ngfftf,tim_fourdp_fock_getghc,gpu_option=gpu_option)
     727       202526 :      call timab(1513,2,tsec) ; call timab(1515,-1,tsec) ; call timab(1544,-1,tsec)
     728              : 
     729       202526 :      if(fockcommon%optstr.and.(fockcommon%ieigen/=0)) then
     730        51840 :        ABI_MALLOC(vfockstr, (6,ndat_occ,ndat))
     731              :        call strfock(fockcommon,gs_ham%gprimd,vfockstr,&
     732              : &                   mpi_enreg,nfftf,ngfftf,fockbz%nkpt_bz,ndat*ndat_occ,rhog_munu,gs_ham%ucvol,&
     733        12960 : &                   qvec_j,gpu_option=gpu_option)
     734        25920 :        do idat=1,ndat
     735        87080 :        do idat_occ=1,ndat_occ
     736       808040 :          fockcommon%stress_ikpt(:,fockcommon%ieigen+idat-1)=fockcommon%stress_ikpt(:,fockcommon%ieigen+idat-1)+vfockstr(:,idat_occ,idat)*occ(idat_occ)*wtk
     737              :        end do ! idat_occ
     738              :        end do ! idat
     739        12960 :        ABI_FREE(vfockstr)
     740        12960 :        if (fockcommon%usepaw==0.and.(.not.need_ghc)) then
     741        11090 :          if (allocated(fockbz%cgocc)) then
     742              : #ifdef HAVE_OPENMP_OFFLOAD
     743              :            !$OMP TARGET EXIT DATA MAP(delete:cwaveocc_r) IF(gpu_option==ABI_GPU_OPENMP)
     744              : #endif
     745        11090 :            ABI_FREE(cwaveocc_r)
     746              :          end if
     747        11090 :          call timab(1524,2,tsec) ; call timab(1544,-2,tsec)
     748        11090 :          cycle
     749              :        end if
     750              :      end if
     751       191436 :      call timab(1524,2,tsec) ; call timab(1544,-2,tsec)
     752              : 
     753              : ! ===================================================
     754              : ! === Calculate the local potential vfockloc_munu ===
     755              : ! ===================================================
     756              : !* Apply the Poisson solver to "rhog_munu" while taking into account the effect of the vector "qvec"
     757              : !* This is precisely what is done in the subroutine hartre, with option cplex=2.
     758              : !* vfock will contain the local Fock potential, the result of hartre routine.
     759              : !* vfock = FFT( rhog_munu/|g+qvec|^2 )
     760       191436 :      call timab(1525,-1,tsec) ; call timab(1545,-1,tsec)
     761              : #if 0
     762              : 
     763              :      do idat=1,ndat
     764              :      do idat_occ=1,ndat_occ
     765              :      call timab(1515,-2,tsec) ; call timab(1513,-1,tsec)
     766              :      call hartre(cplex_fock,fockcommon%gsqcut,fockcommon%usepaw,mpi_enreg,nfftf,ngfftf,&
     767              : &     mpi_enreg%paral_kgb,rhog_munu(:,:,idat_occ,idat),rprimd,vfock(:,idat_occ,idat),divgq0=fock%divgq0,qpt=qvec_j)
     768              :      call timab(1513,2,tsec) ; call timab(1515,-1,tsec)
     769              :      end do ! idat_occ
     770              :      end do ! idat
     771              : 
     772              : #else
     773       191436 :      if(gpu_option==ABI_GPU_DISABLED) then
     774              :        !$OMP PARALLEL DO COLLAPSE(2)
     775       382872 :        do idat=1,ndat
     776      1242043 :        do idat_occ=1,ndat_occ
     777   3863349637 :        do ifft=1,nfftf
     778   3862299030 :          rhog_munu(1,ifft,idat_occ,idat) = rhog_munu(1,ifft,idat_occ,idat) * vqg(ifft)
     779   3863158201 :          rhog_munu(2,ifft,idat_occ,idat) = rhog_munu(2,ifft,idat_occ,idat) * vqg(ifft)
     780              :        end do
     781              :        end do ! idat_occ
     782              :        end do ! idat
     783              :      else if(gpu_option==ABI_GPU_OPENMP) then
     784              : #ifdef HAVE_OPENMP_OFFLOAD
     785              :        !$OMP TARGET TEAMS DISTRIBUTE COLLAPSE(2) &
     786              :        !$OMP& MAP(to:rhog_munu,vqg) PRIVATE(idat,idat_occ)
     787              :        do idat=1,ndat
     788              :        do idat_occ=1,ndat_occ
     789              :        !$OMP PARALLEL DO PRIVATE(ifft)
     790              :        do ifft=1,nfftf
     791              :          rhog_munu(1,ifft,idat_occ,idat) = rhog_munu(1,ifft,idat_occ,idat) * vqg(ifft)
     792              :          rhog_munu(2,ifft,idat_occ,idat) = rhog_munu(2,ifft,idat_occ,idat) * vqg(ifft)
     793              :        end do
     794              :        end do ! idat_occ
     795              :        end do ! idat
     796              : #endif
     797              :      end if ! gpu_option
     798              : 
     799       191436 :      call timab(1515,2,tsec) ; call timab(1513,-1,tsec) ; call timab(1545,-2,tsec)
     800       191436 :      call fourdp(cplex_fock,rhog_munu,vfock,+1,mpi_enreg,nfftf,ndat*ndat_occ,ngfftf,tim_fourdp_fock_getghc,gpu_option=gpu_option)
     801       191436 :      call timab(1513,2,tsec) ; call timab(1515,-1,tsec) ; call timab(1545,-1,tsec)
     802              : #endif
     803       191436 :      call timab(1525,-2,tsec) ; call timab(1545,-2,tsec)
     804              : 
     805              : !===============================================================
     806              : !======== Calculate Dij_Fock_hat contribution in case of PAW ===
     807              : !===============================================================
     808              : 
     809       191436 :      call timab(1526,-1,tsec) ; call timab(1546,-1,tsec)
     810              : 
     811       191436 :      if (fockcommon%usepaw==1) then
     812        38712 :        qphon=qvec_j;nfftotf=product(ngfftf(1:3))
     813         9678 :        ndij=nspden_fock
     814              :        ! dimekb1 is dimensioned as cplex_dij*lmnmax*(lmnmax+1)/2
     815         9678 :        cplex_dij=2*gs_ham%dimekb1/(gs_ham%lmnmax*(gs_ham%lmnmax+1))
     816        67746 :        ABI_MALLOC(dijhat,(gs_ham%dimekb1,natom,ndij,ndat_tot,cplex_fock))
     817      5861730 :        dijhat=zero
     818              : 
     819              : #ifdef HAVE_OPENMP_OFFLOAD
     820              :        !!$OMP TARGET UPDATE FROM(vfock) IF(gpu_option==ABI_GPU_OPENMP)
     821              : #endif
     822         9678 :        iatm=0
     823        20070 :        do itypat=1,gs_ham%ntypat
     824        10392 :          lmn2_size=fockcommon%pawtab(itypat)%lmn2_size
     825        51960 :          ABI_MALLOC(dijhat_tmp,(cplex_fock*cplex_dij*lmn2_size,ndij*ndat_occ*ndat,gs_ham%nattyp(itypat)))
     826              :          call pawdijhat_ndat(dijhat_tmp,cplex_dij,cplex_fock,gs_ham%gprimd,iatm,&
     827              : &           natom,ndij,nfftf,nfftotf,nspden_fock,nspden_fock,ndat_occ*ndat,&
     828              : &           gs_ham%nattyp(itypat),fockbz%pawang,fockcommon%pawfgrtab,&
     829              : &           fockcommon%pawtab(itypat),vfock,qphon,gs_ham%ucvol,gs_ham%xred,&
     830        10392 : &           gpu_option=gpu_option)
     831              :          !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(ia,idat,idat_occ,idat_tot,ii,iatom,ind)
     832        29748 :          do ia=1,gs_ham%nattyp(itypat)
     833        49104 :            do idat=1,ndat
     834       115458 :              do idat_occ=1,ndat_occ
     835        76746 :                idat_tot=(idat-1)*ndat_occ+idat_occ
     836        76746 :                iatom=iatm+ia
     837       249594 :                do ii=1,cplex_fock
     838       153492 :                  ind=(ii-1)*lmn2_size*cplex_dij
     839              :                  dijhat(1:cplex_dij*lmn2_size,iatom,:,idat_tot,ii)=&
     840              :   &                dijhat_tmp(ind+1:ind+cplex_dij*lmn2_size,&
     841      5761800 :                              1+(idat_occ-1)*ndij+(idat-1)*ndat_occ*ndij:idat_occ*ndij+(idat-1)*ndat_occ*ndij,ia)
     842              :                end do
     843              :              end do ! idat_occ
     844              :            end do ! idat
     845              :          end do ! ia
     846        10392 :          ABI_FREE(dijhat_tmp)
     847        20070 :          iatm=iatm+gs_ham%nattyp(itypat)
     848              :        end do
     849              : 
     850              :        !*NOTE Build a replica of cwaveocc_prj covering the full ndat*ndat_occ batch: cwaveocc_prj
     851              :        !*itself does not depend on idat, but gemm_nonlop requires cprjin to be sized on the
     852              :        !*full batch passed as its "ndat" argument.
     853              :        !*This is a bit tedious but remains cheaper than calling nonlop ndat times
     854       153831 :        ABI_MALLOC(cwaveocc_prj_rep,(natom,nspinor*ndat_tot))
     855        29034 :        call pawcprj_alloc(cwaveocc_prj_rep,cwaveocc_prj(1,1)%ncpgr,cwaveocc_prj(:,1)%nlmn)
     856        19356 :        do idat=1,ndat
     857              :          call pawcprj_copy(cwaveocc_prj,&
     858        19356 :          &                 cwaveocc_prj_rep(:,(idat-1)*nspinor*ndat_occ+1:idat*nspinor*ndat_occ))
     859              :        end do
     860              : 
     861         9678 :        signs=2; cpopt=2;idir=0; paw_opt=1;nnlout=1;tim_nonlop=17
     862              : 
     863         9678 :        if(need_ghc) then
     864         7712 :          choice=1
     865         7712 :          call timab(1515,2,tsec) ; call timab(1514,-1,tsec) ; call timab(1546,-2,tsec)
     866              :          call nonlop(choice,cpopt,cwaveocc_prj_rep,enlout_dum,gs_ham,idir,(/zero/),&
     867              :          &           mpi_enreg,ndat_tot,nnlout,paw_opt,signs,gsc_dum,tim_nonlop,vectin_dum,&
     868              :          &           gvnlxc,enl_ndat=dijhat,&
     869         7712 :          &           select_k=K_H_KPRIME)
     870              : 
     871         7712 :          if(gpu_option==ABI_GPU_DISABLED) then
     872        15424 :            do idat=1,ndat
     873        45928 :              do idat_occ=1,ndat_occ
     874        30504 :                idat_tot=(idat-1)*ndat_occ+idat_occ
     875              :                ghc2(:,1+(idat-1)*npw*nspinor:idat*npw*nspinor) = ghc2(:,1+(idat-1)*npw*nspinor:idat*npw*nspinor)&
     876     24180404 :                &                    - gvnlxc(:,1+(idat_tot-1)*npw*nspinor:idat_tot*npw*nspinor) * occ(idat_occ) * wtk
     877              :              end do ! idat_occ
     878              :            end do ! idat
     879              :          else if(gpu_option==ABI_GPU_OPENMP) then
     880              : #ifdef HAVE_OPENMP_OFFLOAD
     881              :            !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
     882              :            !$OMP& MAP(to:gvnlxc,ghc2,occ) PRIVATE(idat,ipw,idat_occ,idat_tot)
     883              :            do idat=1,ndat
     884              :              do ipw=1,npw
     885              :                do idat_occ=1,ndat_occ
     886              :                  idat_tot=(idat-1)*ndat_occ+idat_occ
     887              :                  ghc2(1,ipw+(idat-1)*npw*nspinor) = ghc2(1,ipw+(idat-1)*npw*nspinor)&
     888              :                  &               - gvnlxc(1,ipw+(idat_tot-1)*npw*nspinor) * occ(idat_occ) * wtk
     889              :                  ghc2(2,ipw+(idat-1)*npw*nspinor) = ghc2(2,ipw+(idat-1)*npw*nspinor)&
     890              :                  &               - gvnlxc(2,ipw+(idat_tot-1)*npw*nspinor) * occ(idat_occ) * wtk
     891              :                end do
     892              :              end do
     893              :            end do ! idat
     894              : #endif
     895              :          end if
     896         7712 :          call timab(1514,2,tsec) ; call timab(1515,-1,tsec) ; call timab(1546,-1,tsec)
     897              :        end if
     898              : 
     899              : ! Forces calculation
     900              : 
     901         9678 :        if (fockcommon%optfor.and.(fockcommon%ieigen/=0)) then
     902        16824 :          ABI_MALLOC(vdotr,(ndat_occ,ndat,3,natom))
     903         8412 :          ABI_MALLOC(vdoti,(ndat_tot))
     904        14020 :          ABI_MALLOC(for1,(ndat_occ,3,natom,ndat))
     905              : #ifdef HAVE_OPENMP_OFFLOAD
     906              :          !$OMP TARGET ENTER DATA MAP(alloc:vdotr,vdoti,for1) IF(gpu_option==ABI_GPU_OPENMP)
     907              : #endif
     908              :          !*NOTE:cwavef_rep replicates cwavef ndat_occ times (per idat block) so that single
     909              :          !*nonlop and dotprod_g_batch_full call can process the whole ndat*ndat_occ batch at once.
     910         8412 :          ABI_MALLOC(cwavef_rep,(2,npw*nspinor*ndat_tot))
     911              : #ifdef HAVE_OPENMP_OFFLOAD
     912              :          !$OMP TARGET ENTER DATA MAP(alloc:cwavef_rep) IF(gpu_option==ABI_GPU_OPENMP)
     913              : #endif
     914         2804 :          if(gpu_option==ABI_GPU_DISABLED) then
     915         5608 :            do idat=1,ndat
     916        16480 :              do idat_occ=1,ndat_occ
     917        10872 :                idat_tot=(idat-1)*ndat_occ+idat_occ
     918              :                cwavef_rep(:,1+(idat_tot-1)*npw*nspinor:idat_tot*npw*nspinor)=&
     919     17315012 :                &                cwavef(:,1+(idat-1)*npw*nspinor:idat*npw*nspinor)
     920              :              end do ! idat_occ
     921              :            end do ! idat
     922              :          else if(gpu_option==ABI_GPU_OPENMP) then
     923              : #ifdef HAVE_OPENMP_OFFLOAD
     924              :            !$OMP TARGET TEAMS DISTRIBUTE COLLAPSE(2) MAP(to:cwavef_rep,cwavef) PRIVATE(idat,idat_occ,idat_tot)
     925              :            do idat=1,ndat
     926              :              do idat_occ=1,ndat_occ
     927              :                idat_tot=(idat-1)*ndat_occ+idat_occ
     928              :                !$OMP PARALLEL DO PRIVATE(ipw)
     929              :                do ipw=1,npw*nspinor
     930              :                  cwavef_rep(1,ipw+(idat_tot-1)*npw*nspinor)=cwavef(1,ipw+(idat-1)*npw*nspinor)
     931              :                  cwavef_rep(2,ipw+(idat_tot-1)*npw*nspinor)=cwavef(2,ipw+(idat-1)*npw*nspinor)
     932              :                end do
     933              :              end do ! idat_occ
     934              :            end do ! idat
     935              : #endif
     936              :          end if
     937       107292 :          choice=2; vdotr=zero;doti=zero;cpopt=4;tim_nonlop=17
     938        11216 :          do idir=1,3
     939        28040 :            do iatom=1,natom
     940        16824 :              call timab(1515,2,tsec) ; call timab(1514,-1,tsec) ; call timab(1546,-2,tsec)
     941              :              call nonlop(choice,cpopt,cwaveocc_prj_rep,enlout_dum,gs_ham,idir,(/zero/),mpi_enreg,&
     942              :              &           ndat_tot,nnlout,paw_opt,signs,gsc_dum,tim_nonlop,vectin_dum,&
     943              :              &           forout,enl_ndat=dijhat,iatom_only=iatom,&
     944        16824 :              &           select_k=K_H_KPRIME)
     945        16824 :              call timab(1514,2,tsec) ; call timab(1515,-1,tsec) ; call timab(1546,-1,tsec)
     946              :              call dotprod_g_batch_full(vdotr(:,:,idir,iatom),vdoti,gs_ham%istwf_k,npw,ndat_tot,2,&
     947        25236 :              &                         cwavef_rep,forout,mpi_enreg%me_g0,mpi_enreg%comm_fft,gpu_option=gpu_option)
     948              :            end do ! iatom
     949              :          end do ! idir
     950              : #ifdef HAVE_OPENMP_OFFLOAD
     951              :          !$OMP TARGET EXIT DATA MAP(delete:cwavef_rep) IF(gpu_option==ABI_GPU_OPENMP)
     952              : #endif
     953         2804 :          ABI_FREE(cwavef_rep)
     954              : 
     955         2804 :          if(gpu_option==ABI_GPU_DISABLED) then
     956         5608 :            do idat=1,ndat
     957        11216 :              do iatom=1,natom
     958        25236 :                do idir=1,3
     959        87664 :                  do idat_occ=1,ndat_occ
     960        65232 :                    esum=0
     961     55569312 :                    do ifft=1,atom_nfgd(iatom)
     962     55504080 :                      ind=atom_ifftsph(ifft,iatom)
     963              :                      esum = esum &
     964              :                      &      + vfock(2*ind-1,idat_occ,idat)*grnhat_12(1,ifft,1,idir,iatom,idat_occ,idat) &
     965     55569312 :                      &      - vfock(2*ind,idat_occ,idat)*grnhat_12(2,ifft,1,idir,iatom,idat_occ,idat)
     966              :                    end do
     967        82056 :                    for1(idat_occ,idir,iatom,idat)=esum
     968              :                  end do ! idat_occ
     969              :                end do ! idir
     970              :              end do ! iatom
     971              :            end do ! idat
     972              :          else if(gpu_option==ABI_GPU_OPENMP) then
     973              : #ifdef HAVE_OPENMP_OFFLOAD
     974              :            !$OMP TARGET TEAMS DISTRIBUTE COLLAPSE(2) &
     975              :            !$OMP& MAP(to:vfock,grnhat_12,for1,atom_nfgd,atom_ifftsph) &
     976              :            !$OMP& PRIVATE(ifft,ind,iatom) PRIVATE(idat_occ,idir,esum)
     977              :            do idat=1,ndat
     978              :              do iatom=1,natom
     979              :                !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(esum,ind,idir,idat_occ,ifft)
     980              :                do idir=1,3
     981              :                  do idat_occ=1,ndat_occ
     982              :                    esum=0
     983              :                    do ifft=1,atom_nfgd(iatom)
     984              :                      ind=atom_ifftsph(ifft,iatom)
     985              :                      esum = esum &
     986              :                      &      + vfock(2*ind-1,idat_occ,idat)*grnhat_12(1,ifft,1,idir,iatom,idat_occ,idat) &
     987              :                      &      - vfock(2*ind,idat_occ,idat)*grnhat_12(2,ifft,1,idir,iatom,idat_occ,idat)
     988              :                    end do
     989              :                    for1(idat_occ,idir,iatom,idat)=esum
     990              :                  end do ! idat_occ
     991              :                end do ! idir
     992              :              end do ! iatom
     993              :            end do ! idat
     994              :            !$OMP TARGET UPDATE FROM(for1)
     995              : #endif
     996              :          end if
     997              : 
     998              :          if(.true.) then
     999              :          !if(gpu_option==ABI_GPU_DISABLED) then
    1000              : #ifdef HAVE_OPENMP_OFFLOAD
    1001              :            !$OMP TARGET UPDATE FROM(vdotr) IF(gpu_option==ABI_GPU_OPENMP)
    1002              : #endif
    1003         5608 :            do idat=1,ndat
    1004        11216 :              do iatom=1,natom
    1005        25236 :                do idir=1,3
    1006        87664 :                  do idat_occ=1,ndat_occ
    1007              :                    for12(idir)=rprimd(1,idir)*for1(idat_occ,1,iatom,idat)&
    1008              :                    &          +rprimd(2,idir)*for1(idat_occ,2,iatom,idat)&
    1009        65232 :                    &          +rprimd(3,idir)*for1(idat_occ,3,iatom,idat)
    1010              :                    forikpt(idir,iatom,idat)=forikpt(idir,iatom,idat)&
    1011              :                    &          - (for12(idir)*gs_ham%ucvol/nfftf+vdotr(idat_occ,idat,idir,iatom))&
    1012        82056 :                    &          * occ(idat_occ) * wtk
    1013              :                  end do ! idat_occ
    1014              :                end do ! idir
    1015              :              end do ! iatom
    1016              :            end do ! idat
    1017              :          end if
    1018              : #ifdef HAVE_OPENMP_OFFLOAD
    1019              :          !$OMP TARGET EXIT DATA MAP(delete:vdotr,vdoti,for1) IF(gpu_option==ABI_GPU_OPENMP)
    1020              : #endif
    1021         2804 :          ABI_FREE(vdotr)
    1022         2804 :          ABI_FREE(vdoti)
    1023         2804 :          ABI_FREE(for1)
    1024              :        end if
    1025              : 
    1026              : ! Stresses calculation
    1027         9678 :        if (fockcommon%optstr.and.(fockcommon%ieigen/=0)) then
    1028         1870 :          signs=2;choice=3;cpopt=4;tim_nonlop=17
    1029              : 
    1030              :        ! first contribution
    1031         9350 :          ABI_MALLOC(vdotr,(ndat_occ,ndat,6,1))
    1032         5610 :          ABI_MALLOC(vdoti,(ndat_tot))
    1033              : #ifdef HAVE_OPENMP_OFFLOAD
    1034              :          !$OMP TARGET ENTER DATA MAP(alloc:vdotr,vdoti) IF(gpu_option==ABI_GPU_OPENMP)
    1035              : #endif
    1036              :          !*cwavef_rep replicates cwavef ndat_occ times (per idat block) so that a single
    1037              :          !*dotprod_g_batch_full call can process the whole ndat*ndat_occ batch at once,
    1038              :          !*matching the merged nonlop call below.
    1039         5610 :          ABI_MALLOC(cwavef_rep,(2,npw*nspinor*ndat_tot))
    1040              : #ifdef HAVE_OPENMP_OFFLOAD
    1041              :          !$OMP TARGET ENTER DATA MAP(alloc:cwavef_rep) IF(gpu_option==ABI_GPU_OPENMP)
    1042              : #endif
    1043         1870 :          if(gpu_option==ABI_GPU_DISABLED) then
    1044         3740 :            do idat=1,ndat
    1045        11225 :              do idat_occ=1,ndat_occ
    1046         7485 :                idat_tot=(idat-1)*ndat_occ+idat_occ
    1047              :                cwavef_rep(:,1+(idat_tot-1)*npw*nspinor:idat_tot*npw*nspinor)=&
    1048      4097380 :                &                cwavef(:,1+(idat-1)*npw*nspinor:idat*npw*nspinor)
    1049              :              end do ! idat_occ
    1050              :            end do ! idat
    1051              :          else if(gpu_option==ABI_GPU_OPENMP) then
    1052              : #ifdef HAVE_OPENMP_OFFLOAD
    1053              :            !$OMP TARGET TEAMS DISTRIBUTE COLLAPSE(2) MAP(to:cwavef_rep,cwavef) PRIVATE(idat,idat_occ,idat_tot)
    1054              :            do idat=1,ndat
    1055              :              do idat_occ=1,ndat_occ
    1056              :                idat_tot=(idat-1)*ndat_occ+idat_occ
    1057              :                !$OMP PARALLEL DO PRIVATE(ipw)
    1058              :                do ipw=1,npw*nspinor
    1059              :                  cwavef_rep(1,ipw+(idat_tot-1)*npw*nspinor)=cwavef(1,ipw+(idat-1)*npw*nspinor)
    1060              :                  cwavef_rep(2,ipw+(idat_tot-1)*npw*nspinor)=cwavef(2,ipw+(idat-1)*npw*nspinor)
    1061              :                end do
    1062              :              end do ! idat_occ
    1063              :            end do ! idat
    1064              : #endif
    1065              :          end if
    1066        13090 :          do idir=1,6
    1067        11220 :            call timab(1515,2,tsec) ; call timab(1514,-1,tsec) ; call timab(1546,-2,tsec)
    1068              :            call nonlop(choice,cpopt,cwaveocc_prj_rep,enlout_dum,gs_ham,idir,(/zero/),mpi_enreg,&
    1069              :            &           ndat_tot,nnlout,paw_opt,signs,gsc_dum,tim_nonlop,vectin_dum,&
    1070        11220 :            &           strout,enl_ndat=dijhat,select_k=K_H_KPRIME)
    1071        11220 :            call timab(1514,2,tsec) ; call timab(1515,-1,tsec) ; call timab(1546,-1,tsec)
    1072              :            call dotprod_g_batch_full(vdotr(:,:,idir,1),vdoti,gs_ham%istwf_k,npw,ndat_tot,2,&
    1073              :            &           cwavef_rep,strout,&
    1074        11220 :            &           mpi_enreg%me_g0,mpi_enreg%comm_fft,gpu_option=gpu_option)
    1075              : #ifdef HAVE_OPENMP_OFFLOAD
    1076              :            !$OMP TARGET UPDATE FROM(vdotr) IF(gpu_option==ABI_GPU_OPENMP)
    1077              : #endif
    1078        24310 :            do idat=1,ndat
    1079        67350 :              do idat_occ=1,ndat_occ
    1080              :                fockcommon%stress_ikpt(idir,fockcommon%ieigen+idat-1)=fockcommon%stress_ikpt(idir,fockcommon%ieigen+idat-1)-&
    1081        56130 :                &             vdotr(idat_occ,idat,idir,1)*occ(idat_occ)*wtk/gs_ham%ucvol
    1082              :              end do ! idat_occ
    1083              :            end do ! idat
    1084              :          end do ! idir
    1085              : #ifdef HAVE_OPENMP_OFFLOAD
    1086              :          !$OMP TARGET EXIT DATA MAP(delete:vdotr,vdoti,cwavef_rep) IF(gpu_option==ABI_GPU_OPENMP)
    1087              : #endif
    1088         1870 :          ABI_FREE(vdotr)
    1089         1870 :          ABI_FREE(vdoti)
    1090         1870 :          ABI_FREE(cwavef_rep)
    1091              : 
    1092         1870 :          stress_ikpt =>  fockcommon%stress_ikpt
    1093         1870 :          ieigen = fockcommon%ieigen
    1094              : 
    1095              :        ! second contribution
    1096              :          !if(.true.) then
    1097         1870 :          if(gpu_option==ABI_GPU_DISABLED) then
    1098              : #ifdef HAVE_OPENMP_OFFLOAD
    1099              :            !$OMP TARGET UPDATE FROM(vfock,grnhat_12) IF(gpu_option==ABI_GPU_OPENMP)
    1100              : #endif
    1101         7480 :            ABI_MALLOC(strdat, (3,3,ndat_occ,ndat))
    1102       101045 :            strdat=zero
    1103         3740 :            do idat=1,ndat
    1104        11225 :              do idat_occ=1,ndat_occ
    1105        31810 :                do idir=1,3
    1106        97305 :                  do idir1=1,3
    1107        67365 :                    esum=0
    1108       202095 :                    do iatom=1,natom
    1109    104707395 :                      do ifft=1,atom_nfgd(iatom)
    1110    104505300 :                        ind = atom_ifftsph(ifft,iatom)
    1111              :                        esum = esum + (vfock(2*ind-1,idat_occ,idat)*grnhat_12(1,ifft,1,idir,iatom,idat_occ,idat)&
    1112              :                        &      - vfock(2*ind,idat_occ,idat)*grnhat_12(2,ifft,1,idir,iatom,idat_occ,idat))&
    1113    104640030 :                        &      * atom_rfgd(idir1,ifft,iatom)
    1114              :                      end do
    1115              :                    end do
    1116        89820 :                    strdat(idir,idir1,idat_occ,idat)=esum
    1117              :                  end do
    1118              :                end do
    1119              :              end do ! idat_occ
    1120              :            end do ! idat
    1121         3740 :            do idat=1,ndat
    1122        11225 :              do idat_occ=1,ndat_occ
    1123        29940 :                do idir=1,3
    1124        29940 :                  fockstr(idir)=strdat(idir,idir,idat_occ,idat)
    1125              :                end do
    1126         7485 :                fockstr(4)=(strdat(3,2,idat_occ,idat)+strdat(2,3,idat_occ,idat))*half
    1127         7485 :                fockstr(5)=(strdat(3,1,idat_occ,idat)+strdat(1,3,idat_occ,idat))*half
    1128         7485 :                fockstr(6)=(strdat(1,2,idat_occ,idat)+strdat(2,1,idat_occ,idat))*half
    1129        54265 :                do idir=1,6
    1130              :                  fockcommon%stress_ikpt(idir,fockcommon%ieigen+idat-1)=fockcommon%stress_ikpt(idir,fockcommon%ieigen+idat-1)+&
    1131        52395 :         &           fockstr(idir)/nfftf*occ(idat_occ)*wtk
    1132              :                end do
    1133              :              end do ! idat_occ
    1134              :            end do ! idat
    1135         1870 :            ABI_FREE(strdat)
    1136              :          else if(gpu_option==ABI_GPU_OPENMP) then
    1137              : #ifdef HAVE_OPENMP_OFFLOAD
    1138              :            ABI_MALLOC(strdat, (3,3,ndat_occ,ndat))
    1139              :            strdat=zero
    1140              :            !$OMP TARGET TEAMS DISTRIBUTE COLLAPSE(4) MAP(tofrom:strdat) &
    1141              :            !$OMP& MAP(to:vfock,grnhat_12,atom_nfgd,atom_rfgd,atom_ifftsph) &
    1142              :            !$OMP& PRIVATE(idat,idat_occ,idir,idir1,esum,iatom)
    1143              :            do idat=1,ndat
    1144              :              do idat_occ=1,ndat_occ
    1145              :                do idir=1,3
    1146              :                  do idir1=1,3
    1147              :                    do iatom=1,natom
    1148              :                      esum=0
    1149              :                      !$OMP PARALLEL DO PRIVATE(ifft,ind) REDUCTION(+:esum)
    1150              :                      do ifft=1,atom_nfgd(iatom)
    1151              :                        ind=atom_ifftsph(ifft,iatom)
    1152              :                        esum = esum + (vfock(2*ind-1,idat_occ,idat)*grnhat_12(1,ifft,1,idir,iatom,idat_occ,idat)&
    1153              :                        &      - vfock(2*ind,idat_occ,idat)*grnhat_12(2,ifft,1,idir,iatom,idat_occ,idat))&
    1154              :                        &      * atom_rfgd(idir1,ifft,iatom)
    1155              :                      end do
    1156              :                      strdat(idir,idir1,idat_occ,idat)=strdat(idir,idir1,idat_occ,idat)+esum
    1157              :                    end do
    1158              :                  end do
    1159              :                end do
    1160              :              end do ! idat_occ
    1161              :            end do ! idat
    1162              :            do idat=1,ndat
    1163              :              do idat_occ=1,ndat_occ
    1164              :                do idir=1,3
    1165              :                  fockstr(idir)=strdat(idir,idir,idat_occ,idat)
    1166              :                end do
    1167              :                fockstr(4)=(strdat(3,2,idat_occ,idat)+strdat(2,3,idat_occ,idat))*half
    1168              :                fockstr(5)=(strdat(3,1,idat_occ,idat)+strdat(1,3,idat_occ,idat))*half
    1169              :                fockstr(6)=(strdat(1,2,idat_occ,idat)+strdat(2,1,idat_occ,idat))*half
    1170              :                do idir=1,6
    1171              :                  stress_ikpt(idir,ieigen+idat-1)=stress_ikpt(idir,ieigen+idat-1)+&
    1172              :         &           fockstr(idir)/nfftf*occ(idat_occ)*wtk
    1173              :                end do
    1174              :              end do ! idat_occ
    1175              :            end do ! idat
    1176              :            ABI_FREE(strdat)
    1177              : #endif
    1178              :          end if
    1179              : 
    1180              :        ! third contribution
    1181         1870 :          if(gpu_option==ABI_GPU_DISABLED) then
    1182         3740 :            do idat=1,ndat
    1183        11225 :              do idat_occ=1,ndat_occ
    1184         7485 :                doti=zero
    1185        22455 :                do iatom=1,natom
    1186     11634155 :                  do ifft=1,atom_nfgd(iatom)
    1187     11611700 :                    ind = atom_ifftsph(ifft,iatom)
    1188              :                    doti = doti &
    1189              :                    &      + vfock(2*ind-1,idat_occ,idat) * rho12(1,ifft,nspinor,idat_occ,idat,iatom)&
    1190     11626670 :                    &      - vfock(2*ind,idat_occ,idat)   * rho12(2,ifft,nspinor,idat_occ,idat,iatom)
    1191              :                  end do
    1192              :                end do
    1193        31810 :                fockcommon%stress_ikpt(1:3,fockcommon%ieigen+idat-1)=fockcommon%stress_ikpt(1:3,fockcommon%ieigen+idat-1)-doti/nfftf*occ(idat_occ)*wtk
    1194              :              end do ! idat_occ
    1195              :            end do ! idat
    1196              :          else if(gpu_option==ABI_GPU_OPENMP) then
    1197              : #ifdef HAVE_OPENMP_OFFLOAD
    1198              :            ABI_MALLOC(strdat, (1,1,ndat_occ,ndat))
    1199              :            strdat=zero
    1200              :            !$OMP TARGET TEAMS DISTRIBUTE COLLAPSE(2) &
    1201              :            !$OMP& MAP(tofrom:strdat) MAP(to:vfock,rho12,atom_nfgd,atom_ifftsph) &
    1202              :            !$OMP& PRIVATE(idat,idat_occ,idir,idir1,doti)
    1203              :            do idat=1,ndat
    1204              :              do idat_occ=1,ndat_occ
    1205              :                doti=zero
    1206              :                !$OMP PARALLEL DO PRIVATE(iatom,ifft,ind) REDUCTION(+:doti)
    1207              :                do iatom=1,natom
    1208              :                  do ifft=1,atom_nfgd(iatom)
    1209              :                    ind = atom_ifftsph(ifft,iatom)
    1210              :                    doti = doti &
    1211              :                    &      + vfock(2*ind-1,idat_occ,idat) * rho12(1,ifft,nspinor,idat_occ,idat,iatom)&
    1212              :                    &      - vfock(2*ind,idat_occ,idat)   * rho12(2,ifft,nspinor,idat_occ,idat,iatom)
    1213              :                  end do
    1214              :                end do
    1215              :                strdat(1,1,idat_occ,idat)=doti
    1216              :              end do ! idat_occ
    1217              :            end do ! idat
    1218              :            do idat=1,ndat
    1219              :              do idat_occ=1,ndat_occ
    1220              :                fockcommon%stress_ikpt(1:3,fockcommon%ieigen+idat-1)=fockcommon%stress_ikpt(1:3,fockcommon%ieigen+idat-1) &
    1221              :                  -strdat(1,1,idat_occ,idat)/nfftf*occ(idat_occ)*wtk
    1222              :              end do ! idat_occ
    1223              :            end do ! idat
    1224              :            ABI_FREE(strdat)
    1225              : #endif
    1226              :          end if
    1227              :        end if ! end stresses
    1228              : 
    1229         9678 :        call pawcprj_free(cwaveocc_prj_rep)
    1230         9678 :        ABI_FREE(cwaveocc_prj_rep)
    1231         9678 :        ABI_FREE(dijhat)
    1232              :      end if !end PAW
    1233       191436 :      call timab(1526,2,tsec) ; call timab(1546,-2,tsec)
    1234              : 
    1235              : ! =============================================================
    1236              : ! === Apply the local potential vfockloc_munu to cwaveocc_r ===
    1237              : ! =============================================================
    1238       191436 :      call timab(1527,-1,tsec)
    1239       191436 :      if(gpu_option==ABI_GPU_DISABLED) then
    1240              :        ABI_UNUSED(esumi)
    1241              :        !$OMP PARALLEL DO &
    1242              :        !$OMP& PRIVATE(ind,recwocc,imcwocc,revloc,imvloc)
    1243       382872 :        do idat=1,ndat
    1244      1242043 :          do idat_occ=1,ndat_occ
    1245     14648932 :            do i3=1,ngfftf(3)
    1246    235971433 :              do i2=1,ngfftf(2)
    1247   4097411292 :                do i1=1,ngfftf(1)
    1248   3862299030 :                  ind=i1+(i2-1)*ngfftf(1)+(i3-1)*ngfftf(2)*ngfftf(1)
    1249   3862299030 :                  revloc=vfock(2*ind-1,idat_occ,idat) ; imvloc=vfock(2*ind,idat_occ,idat)
    1250   3862299030 :                  recwocc=cwaveocc_r(1,i1,i2,i3,idat_occ)
    1251   3862299030 :                  imcwocc=cwaveocc_r(2,i1,i2,i3,idat_occ)
    1252   3862299030 :                  vlocpsi_r(2*ind-1,idat)=vlocpsi_r(2*ind-1,idat)-(revloc*recwocc-imvloc*imcwocc)*occ(idat_occ)*wtk
    1253   4083812967 :                  vlocpsi_r(2*ind  ,idat)=vlocpsi_r(2*ind  ,idat)-(revloc*imcwocc+imvloc*recwocc)*occ(idat_occ)*wtk
    1254              :                end do
    1255              :              end do
    1256              :            end do
    1257              :          end do ! idat_occ
    1258              :        end do ! idat
    1259              :      else if(gpu_option==ABI_GPU_OPENMP) then
    1260              : #ifdef HAVE_OPENMP_OFFLOAD
    1261              :        !$OMP TARGET TEAMS DISTRIBUTE COLLAPSE(3) &
    1262              :        !$OMP& MAP(to:vlocpsi_r,cwaveocc_r,occ,vfock) PRIVATE(idat,i3,i2)
    1263              :        do idat=1,ndat
    1264              :          do i3=1,ngfftf(3)
    1265              :            do i2=1,ngfftf(2)
    1266              :              !$OMP PARALLEL DO PRIVATE(ind,i1,idat_occ,recwocc,imcwocc,revloc,imvloc,esum,esumi)
    1267              :              do i1=1,ngfftf(1)
    1268              :                ind=i1+(i2-1)*ngfftf(1)+(i3-1)*ngfftf(2)*ngfftf(1)
    1269              :                esum=zero ; esumi=zero
    1270              :                do idat_occ=1,ndat_occ
    1271              :                  revloc=vfock(2*ind-1,idat_occ,idat) ; imvloc=vfock(2*ind,idat_occ,idat)
    1272              :                  recwocc=cwaveocc_r(1,i1,i2,i3,idat_occ)
    1273              :                  imcwocc=cwaveocc_r(2,i1,i2,i3,idat_occ)
    1274              :                  esum=esum+(revloc*recwocc-imvloc*imcwocc)*occ(idat_occ)
    1275              :                  esumi=esumi+(revloc*imcwocc+imvloc*recwocc)*occ(idat_occ)
    1276              :                end do
    1277              :                vlocpsi_r(2*ind-1,idat)=vlocpsi_r(2*ind-1,idat)-esum*wtk
    1278              :                vlocpsi_r(2*ind  ,idat)=vlocpsi_r(2*ind  ,idat)-esumi*wtk
    1279              :              end do
    1280              :            end do
    1281              :          end do
    1282              :        end do ! idat
    1283              : #endif
    1284              :      end if
    1285       191436 :      if (allocated(fockbz%cgocc)) then
    1286              : #ifdef HAVE_OPENMP_OFFLOAD
    1287              :        !$OMP TARGET EXIT DATA MAP(delete:cwaveocc_r) IF(gpu_option==ABI_GPU_OPENMP)
    1288              : #endif
    1289       191436 :        ABI_FREE(cwaveocc_r)
    1290              :      end if
    1291       393962 :      call timab(1527,2,tsec)
    1292              :    end do ! jband
    1293              : 
    1294              : ! ========================================================
    1295              : ! === End of loop : update of shifts and deallocations ===
    1296              : ! ==============================:=========================
    1297              : !* Update of the shifts to be applied (reminder : mkmem is not 0, nspinor=1)
    1298       202526 :    call timab(1528,1,tsec)
    1299       202526 :    jcg=jcg+npwj*nband_k
    1300       202526 :    jbg=jbg+nband_k
    1301       202526 :    bdtot_jindex=bdtot_jindex+nband_k
    1302       202526 :    jkg=jkg+npwj
    1303       202526 :    if (fockcommon%usepaw==1) then
    1304         9678 :      ABI_FREE(enlout_dum)
    1305         9678 :      ABI_FREE(vectin_dum)
    1306         9678 :      ABI_FREE(ffnl_kp_dum)
    1307         9678 :      ABI_FREE(kpg_kp)
    1308              :    end if
    1309       202526 :    if (associated(gs_ham%ph3d_kp)) then
    1310       202526 :      ABI_FREE(gs_ham%ph3d_kp)
    1311              :    end if
    1312              : #ifdef HAVE_OPENMP_OFFLOAD
    1313              :    !$OMP TARGET EXIT DATA MAP(delete:rhor_munu,rhog_munu,vfock,occ,rho12,gvnlxc) IF(gpu_option==ABI_GPU_OPENMP)
    1314              : #endif
    1315       202526 :    ABI_FREE(rhor_munu)
    1316       202526 :    ABI_FREE(rhog_munu)
    1317       202526 :    ABI_FREE(vfock)
    1318       202526 :    ABI_FREE(occ)
    1319              :   !*Additional arrays in case of paw
    1320       202526 :    if (fockcommon%usepaw==1) then
    1321         9678 :      if ((fockcommon%optfor).and.(fockcommon%ieigen/=0)) then
    1322              : #ifdef HAVE_OPENMP_OFFLOAD
    1323              :        !$OMP TARGET EXIT DATA MAP(delete:forout) IF(gpu_option==ABI_GPU_OPENMP)
    1324              : #endif
    1325         2804 :        ABI_FREE(forout)
    1326              :      end if
    1327         9678 :      if (fockcommon%optstr.and.(fockcommon%ieigen/=0)) then
    1328              : #ifdef HAVE_OPENMP_OFFLOAD
    1329              :        !$OMP TARGET EXIT DATA MAP(delete:strout) IF(gpu_option==ABI_GPU_OPENMP)
    1330              : #endif
    1331         1870 :        ABI_FREE(strout)
    1332              :      end if
    1333              : #ifdef HAVE_OPENMP_OFFLOAD
    1334              :      !$OMP TARGET EXIT DATA MAP(delete:grnhat_12) IF(gpu_option==ABI_GPU_OPENMP .and. ider==3)
    1335              :      !$OMP TARGET EXIT DATA MAP(delete:rho12,gvnlxc) IF(gpu_option==ABI_GPU_OPENMP)
    1336              :      !$OMP TARGET EXIT DATA MAP(delete:atom_ifftsph,atom_nfgd,atom_rfgd) IF(gpu_option==ABI_GPU_OPENMP)
    1337              : #endif
    1338         9678 :      ABI_FREE(grnhat_12)
    1339         9678 :      ABI_FREE(gvnlxc)
    1340         9678 :      ABI_FREE(grnhat12)
    1341         9678 :      ABI_FREE(rho12)
    1342         9678 :      ABI_FREE(atom_ifftsph)
    1343         9678 :      ABI_FREE(atom_nfgd)
    1344         9678 :      ABI_FREE(atom_rfgd)
    1345              :    end if
    1346              : 
    1347       231529 :    call timab(1528,2,tsec)
    1348              : 
    1349              :  end do ! jkpt
    1350              : 
    1351              : ! ========================================================
    1352              : ! === After loop                                       ===
    1353              : ! ========================================================
    1354              : 
    1355        29003 :  call timab(1506,2,tsec) ; call timab(1507,1,tsec) ; call timab(1547,-1,tsec)
    1356              : 
    1357        29003 :  if (fockcommon%usepaw==1) then
    1358         2061 :    if ((fockcommon%optfor).and.(fockcommon%ieigen/=0)) then
    1359         1052 :      call timab(1547,2,tsec) ; call timab(1548,-1,tsec)
    1360         1052 :      call xmpi_sum(forikpt,mpi_enreg%comm_hf,ier)
    1361         1052 :      call timab(1548,2,tsec) ; call timab(1547,-1,tsec)
    1362         2104 :      do idat=1,ndat
    1363         4208 :        do iatom=1,natom !Loop over atom
    1364         2104 :          ia=gs_ham%atindx(iatom)
    1365        15780 :          fockcommon%forces_ikpt(:,ia,fockcommon%ieigen+idat-1)=forikpt(:,iatom,idat)
    1366              :        end do
    1367              :      end do
    1368              :    end if
    1369              :  end if
    1370        29003 :  if(fockcommon%optstr.and.(fockcommon%ieigen/=0)) then
    1371         2040 :    call timab(1547,2,tsec) ; call timab(1548,-1,tsec)
    1372         2040 :    call xmpi_sum(fockcommon%stress_ikpt,mpi_enreg%comm_hf,ier)
    1373         2040 :    call timab(1548,2,tsec) ; call timab(1547,-1,tsec)
    1374              :  end if
    1375              : 
    1376        29003 :  if (.not.need_ghc) then
    1377              : 
    1378              : ! ===============================
    1379              : ! === Deallocate local arrays ===
    1380              : ! ===============================
    1381              : #ifdef HAVE_OPENMP_OFFLOAD
    1382              :    !$OMP TARGET EXIT DATA MAP(delete:cwavef_r,vqg,vlocpsi_r) IF(gpu_option==ABI_GPU_OPENMP)
    1383              : #endif
    1384         2052 :    ABI_FREE(cwavef_r)
    1385         2052 :    ABI_FREE(vlocpsi_r)
    1386         2052 :    ABI_FREE(dummytab)
    1387         2052 :    ABI_FREE(vqg)
    1388         2052 :    if(fockcommon%usepaw==1.or.fockcommon%optstr) then
    1389         2052 :      ABI_FREE(gboundf)
    1390              :    end if
    1391         2052 :    if (fockcommon%usepaw==1) then
    1392          214 :      if ((fockcommon%optfor).and.(fockcommon%ieigen/=0)) then
    1393          136 :        ABI_FREE(forikpt)
    1394              :      end if
    1395              :    end if
    1396              : !*Restore gs_ham datastructure
    1397              : 
    1398         2052 :    if (associated(gs_ham%ph3d_kp)) then
    1399            0 :      ABI_MALLOC(gs_ham%ph3d_kp,(2,gs_ham%npw_k,gs_ham%matblk))
    1400              :    end if
    1401              :    call gs_ham%load_kprime(kpt_kp=gs_ham%kpt_k,istwf_kp=gs_ham%istwf_k,&
    1402         2052 : &   npw_kp=gs_ham%npw_k,kg_kp=gs_ham%kg_k,ffnl_kp=gs_ham%ffnl_k,ph3d_kp=gs_ham%ph3d_k)
    1403              : 
    1404              : !   if (fockcommon%ieigen/=0) fockcommon%ieigen=0
    1405              : 
    1406              :  else
    1407              : 
    1408              : !  *Restore gs_ham datastructure
    1409              : 
    1410        26951 :    if (associated(gs_ham%ph3d_kp)) then
    1411            0 :      ABI_MALLOC(gs_ham%ph3d_kp,(2,gs_ham%npw_k,gs_ham%matblk))
    1412              :    end if
    1413              :    call gs_ham%load_kprime(kpt_kp=gs_ham%kpt_k,istwf_kp=gs_ham%istwf_k,&
    1414        26951 : &   npw_kp=gs_ham%npw_k,kg_kp=gs_ham%kg_k,ffnl_kp=gs_ham%ffnl_k,ph3d_kp=gs_ham%ph3d_k)
    1415              : 
    1416              : !  * Perform an FFT using fourwf to get ghc1 = FFT^-1(vlocpsi_r)
    1417              : #ifdef HAVE_OPENMP_OFFLOAD
    1418              :    !$OMP TARGET UPDATE FROM(vlocpsi_r) IF(gpu_option==ABI_GPU_OPENMP)
    1419              : #endif
    1420       134755 :    ABI_MALLOC(psilocal,(cplex_fock*n4f,n5f,n6f*ndat))
    1421        53902 :    do idat=1,ndat
    1422              :      call fftpac(1,mpi_enreg,nspden_fock,cplex_fock*n1f,n2f,n3f,&
    1423        53902 :        cplex_fock*n4f,n5f,n6f,ngfft,vlocpsi_r(:,idat),psilocal(:,:,1+(idat-1)*n6f:idat*n6f),2)
    1424              :    end do ! idat
    1425              : 
    1426        26951 :    call timab(1515,2,tsec) ; call timab(1512,-1,tsec) ; call timab(1547,-2,tsec)
    1427              :    call fourwf(0,rhodum0,rhodum,ghc1,psilocal,gboundf,gboundf,gs_ham%istwf_k,gs_ham%kg_k,gs_ham%kg_k,&
    1428              : &   mgfftf,mpi_enreg,ndat,ngfftf,1,npw,n4f,n5f,n6f,3,tim_fourwf_fock_getghc,weight1,weight1,&
    1429        26951 : &   gpu_option=gs_ham%gpu_option)
    1430        26951 :    call timab(1512,2,tsec) ; call timab(1515,-1,tsec) ; call timab(1547,-1,tsec)
    1431        26951 :    ABI_FREE(psilocal)
    1432              : 
    1433        26951 :    if(gpu_option==ABI_GPU_DISABLED) then
    1434     20075920 :      ghc1=ghc1*sqrt(gs_ham%ucvol)+ghc2
    1435            0 :    else if(gpu_option==ABI_GPU_OPENMP) then
    1436            0 :      call abi_xaxpy(npw*ndat,cucvol,ghc1,1,ghc2,1,x_cplx=2,gpu_option=gpu_option)
    1437              : #ifdef HAVE_OPENMP_OFFLOAD
    1438              :      call gpu_copy(ghc1,ghc2,int(2,c_size_t)*npw*ndat)
    1439              :      !$OMP TARGET UPDATE FROM(ghc1)
    1440              : #endif
    1441              :    end if
    1442              : 
    1443              : !  * If the calculation is parallelized, perform an MPI_allreduce to sum all the contributions in the array ghc
    1444     20048969 :    ghc(:,:)=ghc(:,:)/mpi_enreg%nproc_hf + ghc1(:,:)
    1445              : 
    1446        26951 :    call timab(1547,2,tsec) ; call timab(1548,-1,tsec)
    1447        26951 :    call xmpi_sum(ghc,mpi_enreg%comm_hf,ier)
    1448        26951 :    call timab(1548,2,tsec) ; call timab(1547,-1,tsec)
    1449              : 
    1450              : !   ===============================
    1451              : !   === Deallocate local PAW arrays ===
    1452              : !   ===============================
    1453        26951 :    if (fockcommon%usepaw==1) then
    1454         1847 :      if ((fockcommon%optfor).and.(fockcommon%ieigen/=0)) then
    1455          916 :        ABI_FREE(forikpt)
    1456              :      end if
    1457              :    end if
    1458        26951 :    if(fockcommon%usepaw==1.or.fockcommon%optstr) then
    1459         1847 :      ABI_FREE(gboundf)
    1460              :    end if
    1461              : !   ============================================
    1462              : !   === Calculate the contribution to energy ===
    1463              : !   ============================================
    1464              : !  * Only the contribution when cwavef=cgocc_bz are calculated, in order to cancel exactly the self-interaction
    1465              : !  * at each convergence step. (consistent definition with the definition of hartree energy)
    1466        26951 :    if (fockcommon%ieigen/=0) then
    1467        53902 :      do idat=1,ndat
    1468              :        eigen=zero
    1469              :   !  * Dot product of cwavef and ghc
    1470              :   !  * inspired from the routine 54_spacepar/meanvalue_g but without the reference to parallelism and filtering
    1471        26951 :        if(gs_ham%istwf_k==2) then
    1472            6 :          eigen=half*cwavef(1,1+(idat-1)*npw)*ghc1(1,1+(idat-1)*npw)
    1473              :        else
    1474        26945 :          eigen=cwavef(1,1+(idat-1)*npw)*ghc1(1,1+(idat-1)*npw)+cwavef(2,1+(idat-1)*npw)*ghc1(2,1+(idat-1)*npw)
    1475              :        end if
    1476      6674006 :        do ipw=2,npw
    1477      6674006 :          eigen=eigen+cwavef(1,ipw+(idat-1)*npw)*ghc1(1,ipw+(idat-1)*npw)+cwavef(2,ipw+(idat-1)*npw)*ghc1(2,ipw+(idat-1)*npw)
    1478              :        end do
    1479        26951 :        if(gs_ham%istwf_k>=2) eigen=two*eigen
    1480        26951 :        call timab(1547,2,tsec) ; call timab(1548,-1,tsec)
    1481        26951 :        call xmpi_sum(eigen,mpi_enreg%comm_hf,ier)
    1482        26951 :        call timab(1548,2,tsec) ; call timab(1547,-1,tsec)
    1483        26951 :        fockcommon%eigen_ikpt(fockcommon%ieigen+idat-1)= eigen
    1484        80853 :        if(fockcommon%use_ACE==0) fockcommon%ieigen = 0
    1485              :      end do ! idat
    1486              :    end if
    1487              : 
    1488              : !   ===============================
    1489              : !   === Deallocate local arrays ===
    1490              : !   ===============================
    1491              : #ifdef HAVE_OPENMP_OFFLOAD
    1492              :    !$OMP TARGET EXIT DATA MAP(delete:cwavef_r,ghc1,ghc2,vqg,vlocpsi_r) IF(gpu_option==ABI_GPU_OPENMP)
    1493              : #endif
    1494        26951 :    ABI_FREE(cwavef_r)
    1495        26951 :    ABI_FREE(ghc1)
    1496        26951 :    ABI_FREE(ghc2)
    1497        26951 :    ABI_FREE(vlocpsi_r)
    1498        26951 :    ABI_FREE(dummytab)
    1499        26951 :    ABI_FREE(vqg)
    1500              : 
    1501              :  endif
    1502              : 
    1503        29003 :  call timab(1504,2,tsec) ; call timab(1507,-2,tsec) ; call timab(1515,-2,tsec) ; call timab(1547,-2,tsec)
    1504              : 
    1505        58006 :  end subroutine fock_getghc
    1506              : !!***
    1507              : 
    1508              : !!****f* ABINIT/fock2ACE
    1509              : !! NAME
    1510              : !! fock2ACE
    1511              : !!
    1512              : !! FUNCTION
    1513              : !! Compute nonlocal contribution to the Fock part of the hamiltonian in the ACE formalism.
    1514              : !! optionally contribution to Fock forces
    1515              : !!
    1516              : !! INPUTS
    1517              : !!  cg(2,mcg)=wavefunctions (may be read from disk file)
    1518              : !!  cprj(natom,mcprj*usecprj)=<p_lmn|Cnk> coefficients for each WF |Cnk> and each NL proj |p_lmn>
    1519              : !!  fock <type(fock_type)>= quantities to calculate Fock exact exchange
    1520              : !!  istwfk(nkpt)=input option parameter that describes the storage of wfs
    1521              : !!  kg(3,mpw*mkmem)=reduced coordinates (integers) of G vecs in basis
    1522              : !!  kpt(3,nkpt)=k points in reduced coordinates
    1523              : !!  mband=maximum number of bands
    1524              : !!  mcg=size of wave-functions array (cg) =mpw*nspinor*mband*mkmem*nsppol
    1525              : !!  mcprj=size of projected wave-functions array (cprj) =nspinor*mband*mkmem*nsppol
    1526              : !!  mgfft=maximum size of 1D FFTs
    1527              : !!  mkmem=number of k points treated by this node.
    1528              : !!  mpi_enreg=information about MPI parallelization
    1529              : !!  mpsang=
    1530              : !!  mpw= maximum number of plane waves
    1531              : !!  my_natom=number of atoms treated by current processor
    1532              : !!  natom=number of atoms in cell.
    1533              : !!  nband(nkpt)=number of bands at each k point
    1534              : !!  nfft=number of FFT grid points
    1535              : !!  ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
    1536              : !!  nkpt=number of k points in Brillouin zone
    1537              : !!  nloalg(3)=governs the choice of the algorithm for non-local operator.
    1538              : !!  npwarr(nkpt)=number of planewaves in basis and boundary at each k
    1539              : !!  nspden=Number of spin Density components
    1540              : !!  nspinor=number of spinorial components of the wavefunctions
    1541              : !!  nsppol=1 for unpolarized, 2 for spin-polarized
    1542              : !!  ntypat=number of types of atoms
    1543              : !!  occ(mband*nkpt*nsppol)=occupation numbers for each band over all k points
    1544              : !!  optfor=1 if computation of forces is required
    1545              : !!  paw_ij(my_natom*usepaw) <type(paw_ij_type)>=paw arrays given on (i,j) channels
    1546              : !!  pawtab(ntypat*usepaw) <type(pawtab_type)>=paw tabulated starting data
    1547              : !!  ph1d(2,3*(2*mgfft+1)*natom)=one-dimensional structure factor information
    1548              : !!  psps <type(pseudopotential_type)>=variables related to pseudopotentials
    1549              : !!  rprimd(3,3)=dimensional primitive translations in real space (bohr)
    1550              : !!  typat(natom)=type of each atom
    1551              : !!  usecprj=1 if cprj datastructure has been allocated
    1552              : !!  gpu_option= GPU implementation to use, i.e. cuda, openMP, ... (0=not using GPU)
    1553              : !!  wtk(nkpt)=weight associated with each k point
    1554              : !!  xred(3,natom)=reduced dimensionless atomic coordinates
    1555              : !!  ylm(mpw*mkmem,mpsang*mpsang*useylm)= real spherical harmonics for each G and k point
    1556              : !!
    1557              : !! OUTPUT
    1558              : !!
    1559              : !! fock%fockACE(ikpt,isppol)%xi
    1560              : !! if optfor=1, fock%fock_common%forces
    1561              : !!
    1562              : !! SOURCE
    1563              : 
    1564         1238 : subroutine fock2ACE(cg,cprj,fock,istwfk,kg,kpt,mband,mcg,mcprj,mgfft,mkmem,mpi_enreg,mpsang,&
    1565         1238 : &  mpw,my_natom,natom,nband,nfft,ngfft,nkpt,nloalg,npwarr,nspden,nspinor,nsppol,&
    1566         1238 : &  ntypat,occ,optfor,paw_ij,pawtab,ph1d,psps,rprimd,typat,usecprj,gpu_option,wtk,xred,ylm)
    1567              : 
    1568              : !Arguments ------------------------------------
    1569              : !scalars
    1570              :  integer,intent(in) :: mband,mcg,mcprj,mgfft,mkmem,mpsang,mpw,my_natom,natom,nfft,nkpt
    1571              :  integer,intent(in) :: nspden,nsppol,nspinor,ntypat,optfor
    1572              :  integer,intent(in) :: usecprj,gpu_option
    1573              :  type(MPI_type),intent(inout) :: mpi_enreg
    1574              :  type(pseudopotential_type),intent(in) :: psps
    1575              : !arrays
    1576              :  integer,intent(in) :: istwfk(nkpt),kg(3,mpw*mkmem),nband(nkpt*nsppol)
    1577              :  integer,intent(in) :: ngfft(18),nloalg(3),npwarr(nkpt)
    1578              :  integer,intent(in) :: typat(natom)
    1579              :  real(dp),intent(in) :: cg(2,mcg)
    1580              :  real(dp),intent(in) :: kpt(3,nkpt)
    1581              :  real(dp),intent(in) :: occ(mband*nkpt*nsppol),ph1d(2,3*(2*mgfft+1)*natom)
    1582              :  real(dp),intent(in) :: rprimd(3,3),wtk(nkpt),xred(3,natom)
    1583              :  real(dp),intent(in) :: ylm(mpw*mkmem,mpsang*mpsang*psps%useylm)
    1584              :  type(pawcprj_type),intent(inout) :: cprj(natom,mcprj*usecprj)
    1585              :  type(paw_ij_type),intent(in) :: paw_ij(my_natom*psps%usepaw)
    1586              :  type(pawtab_type),intent(in) :: pawtab(ntypat*psps%usepaw)
    1587              :  type(fock_type),pointer, intent(inout) :: fock
    1588              : !Local variables-------------------------------
    1589              : !scalars
    1590              :  integer :: bandpp,bdtot_index,dimffnl,iband,iband_cprj,iband_last,ibg,icg,ider
    1591              :  integer :: ierr,info,idir,ikg,ikpt,ilm,ipw,isppol,istwf_k,kk,ll
    1592              :  integer :: mband_cprj,me_distrb,my_ikpt,my_nspinor,nband_k,nband_cprj_k,nkpg
    1593              :  integer :: npw_k,spaceComm
    1594              :  integer :: use_ACE_old
    1595              :  integer :: blocksize,iblock,jblock,iblocksize,jblocksize,nblockbd
    1596              : !integer, save :: counter=0
    1597         1238 :  type(gs_hamiltonian_type) :: gs_hamk
    1598              :  logical :: compute_gbound
    1599              :  character(len=500) :: msg
    1600              :  type(fock_common_type),pointer :: fockcommon
    1601              : !arrays
    1602         1238 :  integer,allocatable :: kg_k(:,:)
    1603              :  real(dp) :: kpoint(3),rmet(3,3),tsec(2)
    1604         1238 :  real(dp),allocatable :: bb(:,:,:),cwavef(:,:),cwavefk(:,:),ffnl_sav(:,:,:,:)
    1605         1238 :  real(dp),allocatable :: kpg_k(:,:),kpg_k_sav(:,:)
    1606         1238 :  real(dp),allocatable :: mkl(:,:,:),occblock(:),ph3d(:,:,:),ph3d_sav(:,:,:)
    1607         1238 :  real(dp),allocatable :: wi(:,:,:),weight(:),ylm_k(:,:),ylmgr_k(:,:,:)
    1608         1238 :  real(dp),allocatable,target :: ffnl(:,:,:,:)
    1609              :  type(bandfft_kpt_type),pointer :: my_bandfft_kpt => null()
    1610         1238 :  type(pawcprj_type),target,allocatable :: cwaveprj(:,:)
    1611              : 
    1612              : !*************************************************************************
    1613              : 
    1614         1238 :  call timab(1560,1,tsec)
    1615         1238 :  call timab(1561,1,tsec)
    1616              : 
    1617              : !DEBUG
    1618              : !if(counter>0)return
    1619              : !counter=counter+1
    1620              : !ENDDEBUG
    1621              : 
    1622              : !Init mpicomm and me
    1623         1238 :  if(mpi_enreg%paral_kgb==1)then
    1624            0 :    spaceComm=mpi_enreg%comm_kpt
    1625            0 :    me_distrb=mpi_enreg%me_kpt
    1626              :  else
    1627              : !* In case of HF calculation
    1628         1238 :    if (mpi_enreg%paral_hf==1) then
    1629            0 :      spaceComm=mpi_enreg%comm_kpt
    1630            0 :      me_distrb=mpi_enreg%me_kpt
    1631              :    else
    1632         1238 :      spaceComm=mpi_enreg%comm_cell
    1633         1238 :      me_distrb=mpi_enreg%me_cell
    1634              :    end if
    1635              :  end if
    1636              : 
    1637              : !Some initializations
    1638         1238 :  my_nspinor=max(1,nspinor/mpi_enreg%nproc_spinor)
    1639         1238 :  compute_gbound=.true.
    1640         1238 :  fockcommon => fock%fock_common
    1641         1238 :  use_ACE_old=fockcommon%use_ACE
    1642         1238 :  fockcommon%use_ACE=0
    1643         1238 :  fockcommon%e_fock0=zero
    1644              : 
    1645              : !Initialize Hamiltonian (k- and spin-independent terms)
    1646              : 
    1647              :  call gs_hamk%init(psps,pawtab,nspinor,nsppol,nspden,natom,&
    1648              : & typat,xred,nfft,mgfft,ngfft,rprimd,nloalg,usecprj=usecprj,&
    1649              : & comm_atom=mpi_enreg%comm_atom,mpi_atmtab=mpi_enreg%my_atmtab,mpi_spintab=mpi_enreg%my_isppoltab,&
    1650              : & paw_ij=paw_ij,ph1d=ph1d,fock=fock,&
    1651         1238 : & gpu_option=gpu_option)
    1652        49520 :  rmet = MATMUL(TRANSPOSE(rprimd),rprimd)
    1653         1238 :  fockcommon%use_ACE=use_ACE_old
    1654              : 
    1655              : !need to reorder cprj=<p_lmn|Cnk> (from unsorted to atom-sorted)
    1656         1238 :  if (psps%usepaw==1) then
    1657          204 :    call pawcprj_reorder(cprj,gs_hamk%atindx)
    1658              :  end if
    1659              : 
    1660              : !LOOP OVER SPINS
    1661         1238 :  bdtot_index=0;ibg=0;icg=0
    1662         1238 :  call timab(1561,2,tsec) ; call timab(1562,-1,tsec)
    1663              : 
    1664         2611 :  do isppol=1,nsppol
    1665         1373 :    fockcommon%isppol=isppol
    1666              : !  Continue to initialize the Hamiltonian (PAW DIJ coefficients)
    1667         1373 :    call gs_hamk%load_spin(isppol,with_nonlocal=.true.)
    1668              : 
    1669              : !  Loop over k points
    1670         1373 :    ikg=0
    1671         9909 :    do ikpt=1,nkpt
    1672         7298 :      fockcommon%ikpt=ikpt
    1673         7298 :      nband_k=nband(ikpt+(isppol-1)*nkpt)
    1674         7298 :      npw_k=npwarr(ikpt)
    1675        29192 :      kpoint(:)=kpt(:,ikpt)
    1676         7298 :      istwf_k=istwfk(ikpt)
    1677         7298 :      if(proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,1,nband_k,isppol,me_distrb)) then
    1678         1720 :        bdtot_index=bdtot_index+nband_k
    1679         1720 :        cycle
    1680              :      end if
    1681              : 
    1682              : !    Parallelism over FFT and/or bands: define sizes and tabs
    1683         5578 :      if (mpi_enreg%paral_kgb==1) then
    1684            0 :        my_ikpt=mpi_enreg%my_kpttab(ikpt)
    1685            0 :        nblockbd=nband_k/(mpi_enreg%nproc_band*mpi_enreg%bandpp)
    1686            0 :        bandpp=mpi_enreg%bandpp
    1687            0 :        my_bandfft_kpt => bandfft_kpt(my_ikpt)
    1688              :      else
    1689         5578 :        my_ikpt=ikpt
    1690         5578 :        bandpp=mpi_enreg%bandpp
    1691         5578 :        nblockbd=nband_k/bandpp
    1692              :      end if
    1693         5578 :      blocksize=nband_k/nblockbd
    1694         5578 :      mband_cprj=mband/mpi_enreg%nproc_band
    1695         5578 :      nband_cprj_k=nband_k/mpi_enreg%nproc_band
    1696              : 
    1697        16734 :      ABI_MALLOC(cwavef,(2,npw_k*my_nspinor*blocksize))
    1698         5578 :      if (psps%usepaw==1) then
    1699         2912 :        ABI_MALLOC(cwaveprj,(natom,my_nspinor*bandpp))
    1700          416 :        call pawcprj_alloc(cwaveprj,0,gs_hamk%dimcprj)
    1701              :      else
    1702         5162 :        ABI_MALLOC(cwaveprj,(0,0))
    1703              :      end if
    1704              : 
    1705        16734 :      ABI_MALLOC(kg_k,(3,mpw))
    1706              : !$OMP PARALLEL DO
    1707      1240915 :      do ipw=1,npw_k
    1708      4946926 :        kg_k(:,ipw)=kg(:,ipw+ikg)
    1709              :      end do
    1710              : 
    1711        22312 :      ABI_MALLOC(ylm_k,(npw_k,mpsang*mpsang*psps%useylm))
    1712         5578 :      ABI_MALLOC(ylmgr_k,(0,0,0))
    1713         5578 :      if (psps%useylm==1) then
    1714              : !$OMP PARALLEL DO COLLAPSE(2)
    1715         2080 :        do ilm=1,mpsang*mpsang
    1716      1280044 :          do ipw=1,npw_k
    1717      1279628 :            ylm_k(ipw,ilm)=ylm(ipw+ikg,ilm)
    1718              :          end do
    1719              :        end do
    1720              :      end if
    1721              : 
    1722              : !    Compute (k+G) vectors
    1723         5578 :      nkpg=3*nloalg(3)
    1724        22312 :      ABI_MALLOC(kpg_k,(npw_k,nkpg))
    1725         5578 :      if (nkpg>0) then
    1726          416 :        call mkkpg(kg_k,kpg_k,kpoint,nkpg,npw_k)
    1727              :      end if
    1728              : 
    1729              : 
    1730              : !    Compute nonlocal form factors ffnl at all (k+G)
    1731         5578 :      ider=0;idir=0;dimffnl=1
    1732        27890 :      ABI_MALLOC(ffnl,(npw_k,dimffnl,psps%lmnmax,ntypat))
    1733              :      call mkffnl(psps%dimekb,dimffnl,psps%ekb,ffnl,psps%ffspl,gs_hamk%gmet,gs_hamk%gprimd,&
    1734              : &     ider,idir,psps%indlmn,kg_k,kpg_k,kpoint,psps%lmnmax,psps%lnmax,psps%mpsang,psps%mqgrid_ff,&
    1735         5578 : &     nkpg,npw_k,ntypat,psps%pspso,psps%qgrid_ff,rmet,psps%usepaw,psps%useylm,ylm_k,ylmgr_k)
    1736              : 
    1737              : !    Load k-dependent part in the Hamiltonian datastructure
    1738              : !     - Compute 3D phase factors
    1739              : !     - Prepare various tabs in case of band-FFT parallelism
    1740              : !     - Load k-dependent quantities in the Hamiltonian
    1741              : 
    1742        22312 :      ABI_MALLOC(ph3d,(2,npw_k,gs_hamk%matblk))
    1743              :      call gs_hamk%load_k(kpt_k=kpoint,istwf_k=istwf_k,npw_k=npw_k,&
    1744         5578 : &     kg_k=kg_k,kpg_k=kpg_k,ffnl_k=ffnl,ph3d_k=ph3d,compute_gbound=compute_gbound,compute_ph3d=.true.)
    1745              : 
    1746              : !    Load band-FFT tabs (transposed k-dependent arrays)
    1747         5578 :      if (mpi_enreg%paral_kgb==1) then
    1748            0 :        call bandfft_kpt_savetabs(my_bandfft_kpt,ffnl=ffnl_sav,ph3d=ph3d_sav,kpg=kpg_k_sav)
    1749            0 :        call prep_bandfft_tabs(gs_hamk,ikpt,mkmem,mpi_enreg)
    1750              :        call gs_hamk%load_k(npw_fft_k=my_bandfft_kpt%ndatarecv, &
    1751              : &       kg_k     =my_bandfft_kpt%kg_k_gather, &
    1752              : &       kpg_k    =my_bandfft_kpt%kpg_k_gather, &
    1753              :        ffnl_k   =my_bandfft_kpt%ffnl_gather, &
    1754            0 :        ph3d_k   =my_bandfft_kpt%ph3d_gather,compute_gbound=compute_gbound)
    1755              :      end if
    1756              : 
    1757              : !    The following is now wrong. In sequential, nblockbd=nband_k/bandpp
    1758              : !    blocksize= bandpp (JB 2016/04/16)
    1759              : !    Note that in sequential mode iblock=iband, nblockbd=nband_k and blocksize=1
    1760              : !
    1761        16734 :      ABI_MALLOC(occblock,(blocksize))
    1762        11156 :      ABI_MALLOC(weight,(blocksize))
    1763        16734 :      occblock=zero;weight=zero
    1764              : 
    1765         5578 :      if (fockcommon%optfor) then
    1766        13345 :        fockcommon%forces_ikpt=zero
    1767              :      end if
    1768              : 
    1769        22312 :      ABI_MALLOC(wi,(2,npw_k*my_nspinor*blocksize,nblockbd))
    1770     20054547 :      wi=zero
    1771        22312 :      ABI_MALLOC(mkl,(2,nband_k,nband_k))
    1772       541338 :      mkl=zero
    1773              : ! Calculate all the Wi for the current k-point
    1774              : 
    1775        32529 :      do iblock=1,nblockbd
    1776              : 
    1777        26951 :        iband=(iblock-1)*blocksize+1;iband_last=min(iband+blocksize-1,nband_k)
    1778        26951 :        iband_cprj=(iblock-1)*bandpp+1
    1779        26951 :        if(proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,iband,iband_last,isppol,me_distrb)) cycle
    1780              : 
    1781              : !      Select occupied bandsddk
    1782        53902 :        occblock(:)=occ(1+(iblock-1)*blocksize+bdtot_index:iblock*blocksize+bdtot_index)
    1783        53902 :        weight(:)=wtk(ikpt)*occblock(:)
    1784              : 
    1785              : !        Load contribution from n,k
    1786              :        cwavef(:,1:npw_k*my_nspinor*blocksize)=&
    1787     20048969 : &       cg(:,1+(iblock-1)*npw_k*my_nspinor*blocksize+icg:iblock*npw_k*my_nspinor*blocksize+icg)
    1788        26951 :        if (psps%usepaw==1) then
    1789              :          call pawcprj_get(gs_hamk%atindx1,cwaveprj,cprj,natom,iband_cprj,ibg,ikpt,0,isppol,&
    1790              : &         mband_cprj,mkmem,natom,bandpp,nband_cprj_k,my_nspinor,nsppol,0,&
    1791         1847 : &         mpicomm=mpi_enreg%comm_kpt,proc_distrb=mpi_enreg%proc_distrb)
    1792              :        end if
    1793              : 
    1794        26951 :        if (mpi_enreg%paral_kgb==1) then
    1795            0 :          msg='fock2ACE: Paral_kgb is not yet implemented for fock calculations'
    1796            0 :          ABI_BUG(msg)
    1797              :        end if
    1798              : 
    1799        26951 :        fockcommon%ieigen=(iblock-1)*blocksize+1
    1800        26951 :        fockcommon%iband=(iblock-1)*blocksize+1
    1801        26951 :        call timab(1562,2,tsec) ; call timab(1563,-1,tsec)
    1802              :        call fock_getghc(cwavef,&
    1803              :              cwaveprj,&
    1804              :              wi(:,:,iblock),&
    1805        26951 :              gs_hamk,mpi_enreg,blocksize)
    1806              : 
    1807              : 
    1808        26951 :        call timab(1563,2,tsec) ; call timab(1562,-1,tsec)
    1809        59480 :        do iblocksize=1,blocksize
    1810        26951 :          mkl(1,fockcommon%ieigen+iblocksize-1,fockcommon%ieigen+iblocksize-1)=fockcommon%eigen_ikpt(fockcommon%ieigen+iblocksize-1)
    1811        26951 :          fockcommon%e_fock0=fockcommon%e_fock0+half*weight(iblocksize)*fockcommon%eigen_ikpt(fockcommon%ieigen+iblocksize-1)
    1812        53902 :          if (fockcommon%optfor) then
    1813        12996 :            fockcommon%forces(:,:)=fockcommon%forces(:,:)+weight(iblocksize)*fockcommon%forces_ikpt(:,:,fockcommon%ieigen+iblocksize-1)
    1814              :          end if
    1815              :        end do
    1816              : 
    1817              : 
    1818              :      end do ! End of loop on block of bands
    1819              : 
    1820              : ! Calculate Mkl for the current k-point
    1821        16734 :      ABI_MALLOC(cwavefk,(2,npw_k*my_nspinor))
    1822        32529 :      do iblock=1,nblockbd
    1823              :        cwavef(:,1:npw_k*my_nspinor*blocksize)=&
    1824     20048969 : &       cg(:,1+(iblock-1)*npw_k*my_nspinor*blocksize+icg:iblock*npw_k*my_nspinor*blocksize+icg)
    1825        59480 :        do iblocksize=1,blocksize
    1826        26951 :          kk=(iblock-1)*blocksize+iblocksize
    1827     20048969 :          cwavefk(:,:)=cwavef(:,1+(iblocksize-1)*npw_k*my_nspinor:iblocksize*npw_k*my_nspinor)
    1828       152179 :          do jblock=1,iblock
    1829       223505 :            do jblocksize=1,blocksize
    1830        98277 :              ll=(jblock-1)*blocksize+jblocksize
    1831       196554 :              if (ll<kk) then
    1832              :                call dotprod_g(mkl(1,kk,ll),mkl(2,kk,ll),gs_hamk%istwf_k,npw_k,2,wi(:,1+(jblocksize-1)*npw_k*my_nspinor:&
    1833        71326 : &               jblocksize*npw_k*my_nspinor,jblock),cwavefk,mpi_enreg%me_g0,mpi_enreg%comm_fft)
    1834              :              end if
    1835              :            end do
    1836              :          end do
    1837              :        end do
    1838              :      end do ! End of loop on block of bands
    1839              : 
    1840         5578 :      ABI_FREE(cwavefk)
    1841       541338 :      mkl=-mkl
    1842              : 
    1843              : ! Cholesky factorisation of -mkl=Lx(trans(L)*. On output mkl=L
    1844         5578 :      call abi_xpotrf("L",nband_k,mkl,nband_k,info,x_cplx=2)
    1845              : 
    1846              : ! calculate trans(L-1)
    1847        16734 :      ABI_MALLOC(bb,(2,nband_k,nband_k))
    1848       541338 :      bb=zero
    1849        32529 :      do kk=1,nband_k
    1850        32529 :        bb(1,kk,kk)=one
    1851              :      end do
    1852         5578 :      call ztrtrs("L","T","N",nband_k,nband_k,mkl,nband_k,bb,nband_k,info)
    1853     20054547 :      fock%fockACE(ikpt,isppol)%xi=zero
    1854              : 
    1855              : ! Calculate ksi
    1856        32529 :      do kk=1,nband_k
    1857       202132 :        do jblock=1,nblockbd
    1858       366157 :          do jblocksize=1,blocksize
    1859       169603 :            ll=(jblock-1)*blocksize+jblocksize
    1860              :            fock%fockACE(ikpt,isppol)%xi(1,:,kk)=fock%fockACE(ikpt,isppol)%xi(1,:,kk)+bb(1,ll,kk)*wi(1,1+(jblocksize-1)*&
    1861              : &           npw_k*my_nspinor:jblocksize*npw_k*my_nspinor,jblock)-&
    1862     42655861 : &           bb(2,ll,kk)*wi(2,1+(jblocksize-1)*npw_k*my_nspinor:jblocksize*npw_k*my_nspinor,jblock)
    1863              :            fock%fockACE(ikpt,isppol)%xi(2,:,kk)=fock%fockACE(ikpt,isppol)%xi(2,:,kk)+bb(1,ll,kk)*wi(2,1+(jblocksize-1)*&
    1864              :            npw_k*my_nspinor:jblocksize*npw_k*my_nspinor,jblock)+&
    1865     42825464 : &           bb(2,ll,kk)*wi(1,1+(jblocksize-1)*npw_k*my_nspinor:jblocksize*npw_k*my_nspinor,jblock)
    1866              :          end do
    1867              :        end do
    1868              :      end do
    1869              : 
    1870              : !    DEBUG
    1871              : !    fock%fockACE(ikpt,isppol)%xi=zero
    1872              : !    ENDDEBUG
    1873              : 
    1874         5578 :      ABI_FREE(wi)
    1875         5578 :      ABI_FREE(mkl)
    1876              : 
    1877              : !    Restore the bandfft tabs
    1878         5578 :      if (mpi_enreg%paral_kgb==1) then
    1879            0 :        call bandfft_kpt_restoretabs(my_bandfft_kpt,ffnl=ffnl_sav,ph3d=ph3d_sav,kpg=kpg_k_sav)
    1880              :      end if
    1881              : 
    1882              : !    Increment indices
    1883         5578 :      bdtot_index=bdtot_index+nband_k
    1884         5578 :      if (mkmem/=0) then
    1885         5578 :        ibg=ibg+my_nspinor*nband_cprj_k
    1886         5578 :        icg=icg+npw_k*my_nspinor*nband_k
    1887         5578 :        ikg=ikg+npw_k
    1888              :      end if
    1889              : 
    1890         5578 :      if (psps%usepaw==1) then
    1891          416 :        call pawcprj_free(cwaveprj)
    1892              :      end if
    1893         6410 :      ABI_FREE(cwaveprj)
    1894         5578 :      ABI_FREE(cwavef)
    1895         5578 :      ABI_FREE(bb)
    1896         5578 :      ABI_FREE(occblock)
    1897         5578 :      ABI_FREE(weight)
    1898         5578 :      ABI_FREE(ffnl)
    1899         5578 :      ABI_FREE(kg_k)
    1900         5578 :      ABI_FREE(kpg_k)
    1901         5578 :      ABI_FREE(ylm_k)
    1902         5578 :      ABI_FREE(ylmgr_k)
    1903         6951 :      ABI_FREE(ph3d)
    1904              :    end do ! End k point loop
    1905              :  end do ! End loop over spins
    1906              : 
    1907         1238 :  call timab(1562,2,tsec)
    1908         1238 :  call timab(1565,1,tsec)
    1909              : 
    1910              : !Parallel case: accumulate (n,k) contributions
    1911              :  if (xmpi_paral==1) then
    1912         1238 :    call xmpi_sum(fockcommon%e_fock0,spaceComm,ierr)
    1913              : !  Forces
    1914         1238 :    if (optfor==1) then
    1915          220 :      if (psps%usepaw==1) then
    1916          144 :        call xmpi_sum(fockcommon%forces,spaceComm,ierr)
    1917              :      end if
    1918              :    end if
    1919              :  end if
    1920              : 
    1921              : !need to reorder cprj=<p_lmn|Cnk> (from atom-sorted to unsorted)
    1922         1238 :  if (psps%usepaw==1) then
    1923          204 :    call pawcprj_reorder(cprj,gs_hamk%atindx1)
    1924              :  end if
    1925              : !Deallocate temporary space
    1926         1238 :  call gs_hamk%free()
    1927              : 
    1928         1238 :  call timab(1565,2,tsec)
    1929         1238 :  call timab(1560,2,tsec)
    1930              : 
    1931         2476 : end subroutine fock2ACE
    1932              : !!***
    1933              : 
    1934              : !!****f* ABINIT/fock_ACE_getghc
    1935              : !! NAME
    1936              : !!  fock_ACE_getghc
    1937              : !!
    1938              : !! FUNCTION
    1939              : !!  Compute the matrix elements <G|Vx|psi> of the Fock operator in the ACE context.
    1940              : !!
    1941              : !! INPUTS
    1942              : !!  cwavef(2,npw*nspinor*ndat)= planewave coefficients of wavefunctions on which Fock operator is applied.
    1943              : !!  gs_ham <type(gs_hamiltonian_type)>=all data for the Hamiltonian to be applied
    1944              : !!  mpi_enreg= information about MPI parallelization
    1945              : !!
    1946              : !! SIDE EFFECTS
    1947              : !!  ghc(2,npw*ndat)= matrix elements <G|H|C> or <G|H-lambda.S|C> (if sij_opt>=0 or =-1 in getghc)
    1948              : !!                   contains the fock exchange term for cwavef at the end.
    1949              : !!
    1950              : !! NOTES
    1951              : !!  The current version assumes that :
    1952              : !!   * nspinor = 1
    1953              : !!   * no "my_nspinor"
    1954              : !!   * no restriction to the value of istwfk_bz (but must be tested in all case)
    1955              : !!   * all the data for the occupied states (cgocc_bz) are the same as those for the current states (cg)
    1956              : !!
    1957              : !! SOURCE
    1958              : 
    1959       142256 : subroutine fock_ACE_getghc(cwavef,ghc,gs_ham,mpi_enreg,ndat,gpu_option)
    1960              : 
    1961              : !Arguments ------------------------------------
    1962              : ! Scalars
    1963              :  integer :: ndat
    1964              :  integer,optional :: gpu_option
    1965              :  type(MPI_type),intent(in) :: mpi_enreg
    1966              :  type(gs_hamiltonian_type),target,intent(inout) :: gs_ham
    1967              : ! Arrays
    1968              :  real(dp),target,intent(inout) :: cwavef(:,:)!,ghc(2,gs_ham%npw_k*ndat)
    1969              :  real(dp),target,intent(inout) :: ghc(:,:)
    1970              : 
    1971              : !Local variables-------------------------------
    1972              : ! Scalars
    1973              :  complex(dp), parameter :: cminusone  = (-1._dp,0._dp)
    1974              :  integer :: iband,ikpt,ipw,my_nspinor,nband_k,npw,idat,gpu_option_
    1975              :  real(dp) :: eigen
    1976              :  type(fock_common_type),pointer :: fockcommon
    1977              : ! Arrays
    1978              :  real(dp) :: tsec(2)
    1979       142256 :  real(dp), target, allocatable :: mat(:,:,:),ghc1(:,:)
    1980       142256 :  real(dp), allocatable :: vdotr(:),vdoti(:)
    1981       142256 :  real(dp), ABI_CONTIGUOUS pointer :: xi(:,:,:)
    1982              : 
    1983              : ! *************************************************************************
    1984              : 
    1985       142256 :  call timab(1580,1,tsec)
    1986              : 
    1987       142256 :  ABI_CHECK(associated(gs_ham%fockcommon),"fock must be associated!")
    1988       142256 :  fockcommon => gs_ham%fockcommon
    1989              : 
    1990       142256 :  ABI_CHECK(gs_ham%nspinor==1,"only allowed for nspinor=1!")
    1991       142256 :  ABI_CHECK(gs_ham%npw_k==gs_ham%npw_kp,"only allowed for npw_k=npw_kp (ground state)!")
    1992              : 
    1993       142256 :  ikpt=fockcommon%ikpt
    1994       142256 :  npw=gs_ham%npw_k
    1995       142256 :  nband_k=fockcommon%nband(ikpt)
    1996       142256 :  my_nspinor=max(1,gs_ham%nspinor/mpi_enreg%nproc_spinor)
    1997       142256 :  gpu_option_=ABI_GPU_DISABLED; if(present(gpu_option)) gpu_option_ = gpu_option
    1998              : !*Initialization of the array ghc1
    1999              : !*ghc1 will contain the exact exchange contribution to the Hamiltonian
    2000       426768 :  ABI_MALLOC(ghc1,(2,npw*my_nspinor*ndat))
    2001    107443100 :  ghc1=zero
    2002              : 
    2003       142256 :  xi => gs_ham%fockACE_k%xi(:,:,:)
    2004              : 
    2005       142256 :  if(gpu_option_==ABI_GPU_DISABLED) then
    2006       142256 :    if(gs_ham%istwf_k==1) then
    2007       568480 :      ABI_MALLOC(mat,(2,nband_k,ndat))
    2008              :      call abi_zgemm_2r('C', 'N', nband_k, ndat, npw, cone, &
    2009              :                        xi, npw, &
    2010              :                        cwavef, npw, &
    2011              :                        czero, &
    2012       142120 :                        mat, nband_k)
    2013              :      call abi_zgemm_2r('N', 'N', npw, ndat, nband_k, cminusone, &
    2014              :                        xi, npw, &
    2015              :                        mat, nband_k, &
    2016              :                        czero, &
    2017       142120 :                        ghc1, npw)
    2018       142120 :      ABI_FREE(mat)
    2019              :    else
    2020          408 :      ABI_MALLOC(vdotr,(nband_k))
    2021          272 :      ABI_MALLOC(vdoti,(nband_k))
    2022          272 :      do idat=1,ndat
    2023              :        call dotprod_g_batch_half(vdotr,vdoti,gs_ham%istwf_k,npw*my_nspinor,nband_k,2,&
    2024          136 :        &    cwavef(:,1+(idat-1)*npw:idat*npw),xi(:,:,:),mpi_enreg%me_g0,mpi_enreg%comm_fft)
    2025              : 
    2026          408 :        do iband=1, nband_k
    2027       820624 :          ghc1(1,1+(idat-1)*npw:idat*npw)=ghc1(1,1+(idat-1)*npw:idat*npw)-vdotr(iband)*xi(1,:,iband)
    2028       820760 :          ghc1(2,1+(idat-1)*npw:idat*npw)=ghc1(2,1+(idat-1)*npw:idat*npw)-vdotr(iband)*xi(2,:,iband)
    2029              :        end do
    2030              :      end do
    2031          136 :      ABI_FREE(vdotr)
    2032          136 :      ABI_FREE(vdoti)
    2033              :    end if
    2034              : 
    2035              :    !* If the calculation is parallelized, perform an MPI_allreduce to sum all the contributions in the array ghc
    2036              :    ! ghc(:,:)=ghc(:,:)/mpi_enreg%nproc_spkpt + ghc1(:,:)
    2037    214886200 :    ghc(:,:)=ghc(:,:) + ghc1(:,:)
    2038              : 
    2039              :    ! call xmpi_sum(ghc,mpi_enreg%comm_kpt,ier)
    2040              : 
    2041              :  else if(gpu_option_==ABI_GPU_OPENMP) then
    2042              : #ifdef HAVE_OPENMP_OFFLOAD
    2043              :    !$OMP TARGET ENTER DATA MAP(alloc:xi,ghc1)
    2044              :    if(gs_ham%istwf_k==1) then
    2045              :      ABI_MALLOC(mat,(2,nband_k,ndat))
    2046              :      !$OMP TARGET ENTER DATA MAP(alloc:mat)
    2047              :      !$OMP TARGET UPDATE TO(xi)
    2048              :      call abi_zgemm_2r('C', 'N', nband_k, ndat, npw, cone, &
    2049              :      &              xi, npw, &
    2050              :      &              cwavef, npw, &
    2051              :      &              czero, &
    2052              :      &              mat, nband_k, &
    2053              :      &              gpu_option=gpu_option_)
    2054              :      call abi_zgemm_2r('N', 'N', npw, ndat, nband_k, cminusone, &
    2055              :      &              xi, npw, &
    2056              :      &              mat, nband_k, &
    2057              :      &              czero, &
    2058              :      &              ghc1, npw, &
    2059              :      &              gpu_option=gpu_option_)
    2060              : 
    2061              :      !$OMP TARGET EXIT DATA MAP(delete:mat)
    2062              :      ABI_FREE(mat)
    2063              :    else
    2064              :      ABI_MALLOC(vdotr,(nband_k))
    2065              :      ABI_MALLOC(vdoti,(nband_k))
    2066              :      !$OMP TARGET ENTER DATA MAP(alloc:vdotr,vdoti)
    2067              :      do idat=1,ndat
    2068              :        call dotprod_g_batch_half(vdotr,vdoti,gs_ham%istwf_k,npw*my_nspinor,nband_k,2,&
    2069              :        &    cwavef(:,1+(idat-1)*npw:idat*npw),xi(:,:,:),mpi_enreg%me_g0,mpi_enreg%comm_fft,&
    2070              :        &    gpu_option=gpu_option_)
    2071              : 
    2072              :        !$OMP TARGET TEAMS DISTRIBUTE PRIVATE(iband) MAP(ghc1,xi,vdotr)
    2073              :        do iband=1, nband_k
    2074              :          !$OMP PARALLEL DO PRIVATE(ipw)
    2075              :          do ipw=1,npw
    2076              :            ghc1(1,ipw+(idat-1)*npw)=ghc1(1,ipw+(idat-1)*npw)-vdotr(iband)*xi(1,ipw,iband)
    2077              :            ghc1(2,ipw+(idat-1)*npw)=ghc1(2,ipw+(idat-1)*npw)-vdotr(iband)*xi(2,ipw,iband)
    2078              :          end do
    2079              :        end do
    2080              :      end do
    2081              :      !$OMP TARGET EXIT DATA MAP(delete:vdotr,vdoti)
    2082              :      ABI_FREE(vdotr)
    2083              :      ABI_FREE(vdoti)
    2084              :    end if
    2085              : 
    2086              :    !* If the calculation is parallelized, perform an MPI_allreduce to sum all the contributions in the array ghc
    2087              :    ! ghc(:,:)=ghc(:,:)/mpi_enreg%nproc_spkpt + ghc1(:,:)
    2088              : 
    2089              :    call abi_xaxpy(npw*ndat,cone,ghc1,1,ghc,1,x_cplx=2,gpu_option=gpu_option)
    2090              : 
    2091              :    ! call xmpi_sum(ghc,mpi_enreg%comm_kpt,ier)
    2092              :    !$OMP TARGET UPDATE FROM(ghc1)
    2093              : 
    2094              :    !$OMP TARGET EXIT DATA MAP(delete:xi,ghc1)
    2095              : #endif
    2096              :  end if
    2097              : 
    2098              : 
    2099              : ! ============================================
    2100              : ! === Calculate the contribution to energy ===
    2101              : ! ============================================
    2102              : !* Only the contribution when cwavef=cgocc_bz are calculated, in order to cancel exactly the self-interaction
    2103              : !* at each convergence step. (consistent definition with the definition of hartree energy)
    2104       142256 :  if (fockcommon%ieigen/=0) then
    2105        68518 :    do idat=1,ndat
    2106        34259 :      eigen=zero
    2107              : !   * Dot product of cwavef and ghc
    2108              : !   * inspired from the routine 54_spacepar/meanvalue_g but without the reference to parallelism and filtering
    2109        34259 :      if(gs_ham%istwf_k==2) then
    2110           29 :        eigen=half*cwavef(1,1+(idat-1)*npw)*ghc1(1,1+(idat-1)*npw)
    2111              :      else
    2112        34230 :        eigen=cwavef(1,1+(idat-1)*npw)*ghc1(1,1+(idat-1)*npw)+cwavef(2,1+(idat-1)*npw)*ghc1(2,1+(idat-1)*npw)
    2113              :      end if
    2114      8415726 :      do ipw=2,npw
    2115      8415726 :        eigen=eigen+cwavef(1,ipw+(idat-1)*npw)*ghc1(1,ipw+(idat-1)*npw)+cwavef(2,ipw+(idat-1)*npw)*ghc1(2,ipw+(idat-1)*npw)
    2116              :      end do
    2117        34259 :      if(gs_ham%istwf_k>=2) eigen=two*eigen
    2118              : !    call xmpi_sum(eigen,mpi_enreg%comm_kpt,ier)
    2119        34259 :      fockcommon%eigen_ikpt(fockcommon%ieigen+idat-1)= eigen
    2120        68518 :      fockcommon%ieigen = 0
    2121              :    end do ! idat
    2122              :  end if
    2123              : 
    2124              : ! ===============================
    2125              : ! === Deallocate local arrays ===
    2126              : ! ===============================
    2127              : 
    2128       142256 :  ABI_FREE(ghc1)
    2129       142256 :  call timab(1580,2,tsec)
    2130              : 
    2131       142256 : end subroutine fock_ACE_getghc
    2132              : !!***
    2133              : 
    2134              : end module m_fock_getghc
    2135              : !!***
        

Generated by: LCOV version 2.3-1