Line data Source code
1 : !!****m* ABINIT/m_getghc
2 : !! NAME
3 : !! m_getghc
4 : !!
5 : !! FUNCTION
6 : !! Compute <G|H|C> for input vector |C> expressed in reciprocal space;
7 : !!
8 : !! COPYRIGHT
9 : !! Copyright (C) 1998-2026 ABINIT group (DCA, XG, GMR, LSI, MT, JB, JWZ)
10 : !! This file is distributed under the terms of the
11 : !! GNU General Public License, see ~abinit/COPYING
12 : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : !!
14 : !! SOURCE
15 :
16 : #if defined HAVE_CONFIG_H
17 : #include "config.h"
18 : #endif
19 :
20 : #include "abi_common.h"
21 :
22 : ! nvtx related macro definition
23 : #include "nvtx_macros.h"
24 :
25 : module m_getghc
26 :
27 : use, intrinsic :: iso_c_binding
28 : use defs_basis
29 : use m_errors
30 : use m_abicore
31 : use m_xmpi
32 : use m_xomp
33 : use m_gputk
34 : use m_abi_linalg
35 :
36 : use defs_abitypes, only : mpi_type
37 : use m_time, only : timab
38 : use m_fstrings, only : sjoin, itoa
39 : use m_cgtools, only : cg_copy_spin, cg_put_spin
40 : use m_pawcprj, only : pawcprj_type, pawcprj_alloc, pawcprj_free, pawcprj_getdim, pawcprj_copy
41 : use m_bandfft_kpt, only : bandfft_kpt, bandfft_kpt_get_ikpt
42 : use m_hamiltonian, only : gs_hamiltonian_type, KPRIME_H_K, K_H_KPRIME, K_H_K, KPRIME_H_KPRIME
43 : use m_fock, only : fock_common_type, fock_get_getghc_call
44 : use m_fock_getghc, only : fock_getghc, fock_ACE_getghc
45 : use m_nonlop, only : nonlop
46 : use m_gemm_nonlop_projectors, only : gemm_nonlop_use_gemm
47 : use m_fft, only : fourwf,fourwf_optmem
48 : use m_ompgpu_fourwf, only : ompgpu_fourwf_work_mem
49 : use m_gemm_nonlop, only : gemm_nonlop_ompgpu_work_mem
50 :
51 : #if defined(HAVE_GPU_MARKERS)
52 : use m_nvtx_data
53 : #endif
54 : #ifdef HAVE_FFTW3_THREADS
55 : use m_fftw3, only : fftw3_spawn_threads_here, fftw3_use_lib_threads
56 : #endif
57 : #if defined HAVE_GPU_CUDA
58 : use m_gpu_toolbox
59 : #endif
60 : #if defined HAVE_YAKL
61 : use gator_mod
62 : #endif
63 : #ifdef HAVE_KOKKOS
64 : use m_manage_kokkos, only : assemble_energy_contribution_kokkos
65 : #endif
66 :
67 : implicit none
68 :
69 : private
70 : !!***
71 :
72 : public :: getghc ! Compute <G|H|C> for input vector |C> expressed in reciprocal space
73 : public :: getgsc ! Compute <G|S|C> for all input vectors |Cnk> at a given k-point
74 : public :: getghc_mGGA
75 : public :: multithreaded_getghc
76 : public :: getghc_nucdip ! compute <G|H_nucdip|C> for input vector |C> expressed in recip space
77 : public :: getghc_ompgpu_work_mem ! assess GPU memory requirements for running getghc with OpenMP GPU
78 : !!***
79 :
80 : contains
81 : !!***
82 :
83 : !!****f* ABINIT/getghc_ompgpu_work_mem
84 : !! NAME
85 : !! getghc_ompgpu_work_mem
86 : !!
87 : !! FUNCTION
88 : !! Returns work memory requirement for getghc_ompgpu
89 : !!
90 : !! INPUTS
91 : !! gs_ham <type(gs_hamiltonian_type)>=contains dimensions of FFT domain
92 : !! ndat=size of batch for fourwf and nonlop processing
93 : !!
94 : !! OUTPUT
95 : !! req_mem=amount in bytes of required memory for getghc_ompgpu
96 :
97 0 : function getghc_ompgpu_work_mem(gs_ham, ndat, nfft_blocks) result(req_mem)
98 :
99 : type(gs_hamiltonian_type),intent(in),target :: gs_ham
100 : integer, intent(in) :: ndat, nfft_blocks
101 : integer(kind=c_size_t) :: req_mem, ghc_mem, nonlop_mem
102 :
103 : ! getghc use a GPU work buffer only when using fourwf
104 : ! Therefore, max GPU memory required by getghc is either:
105 : ! - the sum of getghc and fourwf work buffers memory requirements
106 : ! - the amount of memory required by gemm_nonlop_ompgpu work buffers
107 0 : ghc_mem = 0
108 0 : ghc_mem = int(2, c_size_t) * dp * gs_ham%n4 * gs_ham%n5 * gs_ham%n6 * (ndat/nfft_blocks + modulo(ndat,nfft_blocks))
109 : !ghc_mem = ghc_mem + ompgpu_fourwf_work_mem(gs_ham%ngfft, ndat)
110 :
111 : nonlop_mem = gemm_nonlop_ompgpu_work_mem(gs_ham%istwf_k, ndat, 0, gs_ham%npw_fft_k,&
112 0 : & gs_ham%indlmn, gs_ham%nattyp, gs_ham%ntypat, gs_ham%lmnmax, 2, 11)
113 :
114 0 : req_mem = MAX(ghc_mem, nonlop_mem)
115 :
116 0 : end function getghc_ompgpu_work_mem
117 : !!***
118 :
119 : !!****f* ABINIT/getghc
120 : !! NAME
121 : !! getghc
122 : !!
123 : !! FUNCTION
124 : !! Compute <G|H|C> for input vector |C> expressed in reciprocal space;
125 : !! Result is put in array ghc.
126 : !! <G|Vnonlocal + VfockACE|C> is also returned in gvnlxc if either NLoc NCPP or FockACE.
127 : !! If required, <G|S|C> is returned in gsc (S=overlap - PAW only)
128 : !! Note that left and right k points can be different, i.e. ghc=<k^prime+G|H|C_k>.
129 : !!
130 : !! INPUTS
131 : !! cpopt=flag defining the status of cwaveprj%cp(:)=<Proj_i|Cnk> scalars (PAW only)
132 : !! (same meaning as in nonlop.F90 routine)
133 : !! if cpopt=-1, <p_lmn|in> (and derivatives) are computed here (and not saved)
134 : !! if cpopt= 0, <p_lmn|in> are computed here and saved
135 : !! if cpopt= 1, <p_lmn|in> and first derivatives are computed here and saved
136 : !! if cpopt= 2 <p_lmn|in> are already in memory;
137 : !! if cpopt= 3 <p_lmn|in> are already in memory; first derivatives are computed here and saved
138 : !! if cpopt= 4 <p_lmn|in> and first derivatives are already in memory;
139 : !! cwavef(2,npw*my_nspinor*ndat)=planewave coefficients of wavefunction.
140 : !! cwavef_r(2,n4,n5,n6,nspinor) = wave function in real space
141 : !! gs_ham <type(gs_hamiltonian_type)>=all data for the Hamiltonian to be applied
142 : !! lambda=factor to be used when computing <G|H-lambda.S|C> - only for sij_opt=-1
143 : !! Typically lambda is the eigenvalue (or its guess)
144 : !! mpi_enreg=information about MPI parallelization
145 : !! ndat=number of FFT to do in parallel
146 : !! prtvol=control print volume and debugging output
147 : !! sij_opt= -PAW ONLY- if 0, only matrix elements <G|H|C> have to be computed
148 : !! (S=overlap) if 1, matrix elements <G|S|C> have to be computed in gsc in addition to ghc
149 : !! if -1, matrix elements <G|H-lambda.S|C> have to be computed in ghc (gsc not used)
150 : !! tim_getghc=timing code of the calling subroutine(can be set to 0 if not attributed)
151 : !! type_calc= option governing which part of Hamitonian is to be applied:
152 : ! 0: whole Hamiltonian
153 : !! 1: local part only
154 : !! 2: non-local+Fock+kinetic only (added to the existing Hamiltonian)
155 : !! 3: local + kinetic only (added to the existing Hamiltonian)
156 : !! ===== Optional inputs =====
157 : !! [kg_fft_k(3,:)]=optional, (k+G) vector coordinates to be used for the FFT transformation
158 : !! instead of the one contained in gs_ham datastructure.
159 : !! Typically used for real WF (in parallel) which are FFT-transformed 2 by 2.
160 : !! [kg_fft_kp(3,:)]=optional, (k^prime+G) vector coordinates to be used for the FFT transformation
161 : !! [select_k]=optional, option governing the choice of k points to be used.
162 : !! gs_ham datastructure contains quantities needed to apply Hamiltonian
163 : !! in reciprocal space between 2 kpoints, k and k^prime (equal in most cases);
164 : !! if select_k=1, <k^prime|H|k> is applied [default]
165 : !! if select_k=2, <k|H|k^prime> is applied
166 : !! if select_k=3, <k|H|k> is applied
167 : !! if select_k=4, <k^prime|H|k^prime> is applied
168 : !!
169 : !! OUTPUT
170 : !! ghc(2,npw*my_nspinor*ndat)=matrix elements <G|H|C> (if sij_opt>=0)
171 : !! or <G|H-lambda.S|C> (if sij_opt=-1)
172 : !! gvnlxc(2,npw*my_nspinor*ndat)=matrix elements <G|Vnonlocal+VFockACE|C> (if sij_opt>=0)
173 : !! or <G|Vnonlocal+VFockACE-lambda.S|C> (if sij_opt=-1)
174 : !! include Vnonlocal if NCPP and non-local Fock if associated(gs_ham%fockcommon)
175 : !! if (sij_opt=1)
176 : !! gsc(2,npw*my_nspinor*ndat)=matrix elements <G|S|C> (S=overlap).
177 : !!
178 : !! SIDE EFFECTS
179 : !! cwaveprj(natom,my_nspinor*(1+cpopt)*ndat)= wave function projected on nl projectors (PAW only)
180 : !!
181 : !! SOURCE
182 :
183 34965650 : subroutine getghc(cpopt,cwavef,cwaveprj,ghc,gsc,gs_ham,gvnlxc,lambda,mpi_enreg,ndat,&
184 : prtvol,sij_opt,tim_getghc,type_calc,&
185 34965650 : kg_fft_k,kg_fft_kp,select_k,cwavef_r,filter_dilatmx_loc) ! optional arguments
186 :
187 : !Arguments ------------------------------------
188 : !scalars
189 : logical,intent(in),optional :: filter_dilatmx_loc
190 : integer,intent(in) :: cpopt,ndat, prtvol
191 : integer,intent(in) :: sij_opt,tim_getghc,type_calc
192 : integer,intent(in),optional :: select_k
193 : real(dp),intent(in) :: lambda
194 : type(MPI_type),intent(in) :: mpi_enreg
195 : type(gs_hamiltonian_type),intent(inout),target :: gs_ham
196 : !arrays
197 : integer,intent(in),optional,target :: kg_fft_k(:,:),kg_fft_kp(:,:)
198 : real(dp),intent(out),target :: gsc(:,:)
199 : real(dp),intent(inout), target :: cwavef(:,:)
200 : real(dp),optional,intent(inout) :: cwavef_r(:,:,:,:,:)
201 : real(dp),intent(out), target :: ghc(:,:)
202 : real(dp),intent(out),target :: gvnlxc(:,:)
203 : type(pawcprj_type),intent(inout),target :: cwaveprj(:,:)
204 : !MG: Passing these arrays assumed-shape has the drawback that client code is
205 : !forced to use vec(2, npw*ndat) instead of the more user-friendly vec(2,npw,ndat)
206 :
207 : !Local variables-------------------------------
208 : !scalars
209 : integer,parameter :: level=114, tim_fourwf=1
210 : integer :: choice,cplex,cpopt_here,fftalg,i1,i2,i3,idat,idir,ierr,i0
211 : integer :: ig,igspinor,istwf_k_,ii,iispinor,ikpt_this_proc,ipw,ispinor,my_nspinor
212 : integer :: n4,n5,n6,ndat_,nnlout,npw_fft,npw_k1,npw_k2,nspinortot,option_fft
213 : integer :: paw_opt,select_k_,shift1,shift2,signs,tim_nonlop
214 : integer :: chunk,residuchunk,nfft_blocks
215 : logical(kind=c_bool) :: k1_eq_k2
216 : logical :: double_rfft_trick,have_to_reequilibrate,has_fock,local_gvnlxc
217 : logical :: nspinor1TreatedByThisProc,nspinor2TreatedByThisProc,use_cwavef_r, filter_dilatmx_loc_
218 : real(dp) :: ghcim,ghcre,weight !, kscale
219 : #ifdef HAVE_OPENMP_OFFLOAD
220 : complex(dp), parameter :: cminusone = (-1._dp,0._dp)
221 : #endif
222 : character(len=500) :: msg
223 : !arrays
224 34965650 : integer, contiguous, pointer :: gbound_k1(:,:), gbound_k2(:,:)
225 34965650 : integer, contiguous, pointer :: kg_k1(:,:), kg_k2(:,:)
226 34965650 : integer, contiguous, pointer :: indices_pw_fft(:), kg_k_fft(:,:)
227 34965650 : integer, contiguous, pointer :: recvcount_fft(:), recvdisp_fft(:)
228 34965650 : integer, contiguous, pointer :: sendcount_fft(:), senddisp_fft(:)
229 34965650 : integer, allocatable:: dimcprj(:)
230 104896950 : real(dp) :: enlout(ndat), lambda_ndat(ndat), tsec(2)
231 : real(dp), target :: nonlop_dum(1,1)
232 34965650 : real(dp), allocatable :: buff_wf(:,:)
233 34965650 : real(dp), allocatable :: cwavef1(:,:)
234 34965650 : real(dp), allocatable :: cwavef2(:,:)
235 34965650 : real(dp), allocatable :: cwavef_fft(:,:)
236 34965650 : real(dp), allocatable :: cwavef_fft_tr(:,:)
237 34965650 : real(dp), allocatable :: ghc1(:,:)
238 34965650 : real(dp), allocatable :: ghc2(:,:)
239 34965650 : real(dp), allocatable :: ghc3(:,:)
240 34965650 : real(dp), allocatable :: ghc4(:,:)
241 34965650 : real(dp), allocatable :: ghc_mGGA(:,:)
242 34965650 : real(dp), allocatable :: ghc_mGGA_fft(:,:)
243 34965650 : real(dp), allocatable :: ghc_vectornd(:,:)
244 34965650 : real(dp), allocatable :: cwavef_spin(:,:), gvnlxc_spin(:,:)
245 :
246 : #if defined HAVE_GPU && defined HAVE_YAKL
247 : real(c_double), contiguous, pointer :: gvnlc(:,:)
248 : real(c_double), contiguous, pointer :: gvnlxc_(:,:)
249 : #else
250 34965650 : real(dp), target, allocatable :: gvnlc(:,:)
251 34965650 : real(dp), contiguous, pointer :: gvnlxc_(:,:)
252 : #endif
253 34965650 : real(dp), allocatable :: vlocal_tmp(:,:,:), work(:,:,:,:)
254 34965650 : real(dp), contiguous, pointer :: kinpw_k1(:), kinpw_k2(:), kpt_k1(:), kpt_k2(:)
255 34965650 : real(dp), contiguous, pointer :: gsc_ptr(:,:)
256 : type(fock_common_type),pointer :: fock
257 34965650 : type(pawcprj_type),pointer :: cwaveprj_fock(:,:),cwaveprj_idat(:,:),cwaveprj_nonlop(:,:)
258 : logical :: transfer_ghc,transfer_gsc,transfer_cwavef,transfer_gvnlxc
259 : real(c_double), parameter :: hugevalue = huge(zero)*1.d-11
260 : ! *********************************************************************
261 :
262 : DBG_ENTER("COLL")
263 :
264 : !Keep track of total time spent in getghc:
265 34965650 : call timab(350+tim_getghc,1,tsec)
266 : ABI_NVTX_START_RANGE(NVTX_GETGHC)
267 :
268 : !Structured debugging if prtvol==-level
269 34965650 : if(prtvol==-level)then
270 0 : write(msg,'(80a,a,a)') ('=',ii=1,80),ch10,' getghc : enter, debugging '
271 0 : call wrtout(std_out,msg,'PERS')
272 : end if
273 :
274 : !Select k-dependent objects according to select_k input parameter
275 34965650 : select_k_=KPRIME_H_K;if (present(select_k)) select_k_=select_k
276 14561182 : select case (select_k_)
277 : case (KPRIME_H_K)
278 : ! <k^prime|H|k>
279 14561182 : npw_k1 = gs_ham%npw_fft_k ; npw_k2 = gs_ham%npw_fft_kp
280 14561182 : kpt_k1 => gs_ham%kpt_k ; kpt_k2 => gs_ham%kpt_kp
281 14561182 : kg_k1 => gs_ham%kg_k ; kg_k2 => gs_ham%kg_kp
282 14561182 : gbound_k1 => gs_ham%gbound_k ; gbound_k2 => gs_ham%gbound_kp
283 14561182 : kinpw_k1 => gs_ham%kinpw_k ; kinpw_k2 => gs_ham%kinpw_kp
284 : case (K_H_KPRIME)
285 : ! <k|H|k^prime>
286 0 : npw_k1 = gs_ham%npw_fft_kp; npw_k2 = gs_ham%npw_fft_k
287 0 : kpt_k1 => gs_ham%kpt_kp ; kpt_k2 => gs_ham%kpt_k
288 0 : kg_k1 => gs_ham%kg_kp ; kg_k2 => gs_ham%kg_k
289 0 : gbound_k1 => gs_ham%gbound_kp ; gbound_k2 => gs_ham%gbound_k
290 0 : kinpw_k1 => gs_ham%kinpw_kp ; kinpw_k2 => gs_ham%kinpw_k
291 : case (K_H_K)
292 : ! <k|H|k>
293 0 : npw_k1 = gs_ham%npw_fft_k ; npw_k2 = gs_ham%npw_fft_k
294 0 : kpt_k1 => gs_ham%kpt_k ; kpt_k2 => gs_ham%kpt_k
295 0 : kg_k1 => gs_ham%kg_k ; kg_k2 => gs_ham%kg_k
296 0 : gbound_k1 => gs_ham%gbound_k ; gbound_k2 => gs_ham%gbound_k
297 0 : kinpw_k1 => gs_ham%kinpw_k ; kinpw_k2 => gs_ham%kinpw_k
298 : case (KPRIME_H_KPRIME)
299 : ! <k^prime|H|k^prime>
300 20404468 : npw_k1 = gs_ham%npw_fft_kp; npw_k2 = gs_ham%npw_fft_kp
301 20404468 : kpt_k1 => gs_ham%kpt_kp ; kpt_k2 => gs_ham%kpt_kp
302 20404468 : kg_k1 => gs_ham%kg_kp ; kg_k2 => gs_ham%kg_kp
303 20404468 : gbound_k1 => gs_ham%gbound_kp ; gbound_k2 => gs_ham%gbound_kp
304 20404468 : kinpw_k1 => gs_ham%kinpw_kp ; kinpw_k2 => gs_ham%kinpw_kp
305 : case default
306 34965650 : ABI_ERROR(sjoin("Invalid select_k: ", itoa(select_k_)))
307 : end select
308 :
309 139485385 : k1_eq_k2=(all(abs(kpt_k1(:)-kpt_k2(:))<tol8))
310 :
311 : ! Check sizes
312 34965650 : my_nspinor=max(1,gs_ham%nspinor/mpi_enreg%nproc_spinor)
313 104896950 : ABI_CHECK_IGEQ(size(cwavef), 2*npw_k1*my_nspinor*ndat, 'wrong size for cwavef!')
314 104896950 : ABI_CHECK_IGEQ(size(ghc), 2*npw_k2*my_nspinor*ndat, 'wrong size for ghc!')
315 34965650 : if (sij_opt==1) then
316 24460182 : ABI_CHECK_IGEQ(size(gsc), 2*npw_k2*my_nspinor*ndat, 'wrong size for gsc!')
317 : end if
318 34965650 : if (gs_ham%usepaw==1.and.cpopt>=0) then
319 7688310 : ABI_CHECK_IGEQ(size(cwaveprj), gs_ham%natom*my_nspinor*ndat, 'wrong size for cwaveprj!')
320 : end if
321 34965650 : if (any(type_calc == [0, 2, 3])) then
322 104273178 : local_gvnlxc = size(gvnlxc)<=1
323 34757726 : if (local_gvnlxc) then
324 880108 : if(gs_ham%gpu_option==ABI_GPU_KOKKOS) then
325 : #if defined HAVE_GPU && defined HAVE_YAKL
326 : ABI_MALLOC_MANAGED(gvnlxc_, (/2,npw_k2*my_nspinor*ndat/))
327 : #endif
328 : else
329 2640324 : ABI_MALLOC(gvnlxc_,(2,npw_k2*my_nspinor*ndat))
330 : end if
331 : else
332 33877618 : gvnlxc_ => gvnlxc
333 : end if
334 104273178 : ABI_CHECK_IGEQ(size(gvnlxc_), 2*npw_k2*my_nspinor*ndat, 'wrong size for gvnlxc!')
335 : end if
336 :
337 34965650 : use_cwavef_r=present(cwavef_r)
338 34965650 : n4=gs_ham%n4 ; n5=gs_ham%n5 ; n6=gs_ham%n6
339 34965650 : nspinortot=gs_ham%nspinor
340 :
341 34965650 : if (use_cwavef_r) then
342 0 : ABI_CHECK_IEQ(size(cwavef_r,1), 2, 'wrong size for cwavef_r (dimension 1)')
343 0 : ABI_CHECK_IEQ(size(cwavef_r,2), n4, 'wrong size for cwavef_r (dimension 2)')
344 0 : ABI_CHECK_IEQ(size(cwavef_r,3), n5, 'wrong size for cwavef_r (dimension 3)')
345 0 : ABI_CHECK_IEQ(size(cwavef_r,4), n6, 'wrong size for cwavef_r (dimension 4)')
346 0 : ABI_CHECK_IEQ(size(cwavef_r,5), nspinortot, 'wrong size for cwavef_r (dimension 5)')
347 : end if
348 :
349 : !Eventually overwrite plane waves data for FFT
350 34965650 : if (present(kg_fft_k)) then
351 3274 : kg_k1 => kg_fft_k ; kg_k2 => kg_fft_k
352 3274 : npw_k1=size(kg_k1,2) ; npw_k2=size(kg_k2,2)
353 : end if
354 34965650 : if (present(kg_fft_kp)) then
355 0 : kg_k2 => kg_fft_kp ; npw_k2=size(kg_k2,2)
356 : end if
357 :
358 : !paral_kgb constraint
359 34965650 : if (mpi_enreg%paral_kgb==1.and.(.not.k1_eq_k2)) then
360 0 : ABI_BUG('paral_kgb=1 not allowed for k/=k_^prime!')
361 : end if
362 :
363 : !Do we add Fock exchange term ?
364 34965650 : has_fock = associated(gs_ham%fockcommon)
365 34965650 : if (has_fock) fock => gs_ham%fockcommon
366 :
367 : !Parallelization over spinors management
368 34965650 : if (mpi_enreg%paral_spinor==0) then
369 34914286 : shift1=npw_k1;shift2=npw_k2
370 34914286 : nspinor1TreatedByThisProc=.true.
371 34914286 : nspinor2TreatedByThisProc=(nspinortot==2)
372 : else
373 51364 : shift1=0;shift2=0
374 51364 : nspinor1TreatedByThisProc=(mpi_enreg%me_spinor==0)
375 51364 : nspinor2TreatedByThisProc=(mpi_enreg%me_spinor==1)
376 : end if
377 :
378 34965650 : filter_dilatmx_loc_ = .true.; if ( present(filter_dilatmx_loc) ) filter_dilatmx_loc_ = filter_dilatmx_loc
379 34965650 : transfer_ghc = .false.; transfer_gsc = .false.; transfer_gvnlxc = .false.; transfer_cwavef = .false.
380 : if(gs_ham%gpu_option == ABI_GPU_OPENMP) then
381 : #ifdef HAVE_OPENMP_OFFLOAD
382 : transfer_ghc = .not. xomp_target_is_present(c_loc(ghc))
383 : transfer_gsc = .not. xomp_target_is_present(c_loc(gsc)) .and. sij_opt==1
384 : transfer_gvnlxc = .not. xomp_target_is_present(c_loc(gvnlxc_))
385 : transfer_cwavef = .not. xomp_target_is_present(c_loc(cwavef))
386 :
387 : !$OMP TARGET ENTER DATA MAP(alloc:ghc) IF(transfer_ghc)
388 : !$OMP TARGET ENTER DATA MAP(alloc:gsc) IF(transfer_gsc)
389 : !$OMP TARGET ENTER DATA MAP(alloc:gvnlxc_) IF(transfer_gvnlxc)
390 : !$OMP TARGET ENTER DATA MAP(to:cwavef) IF(transfer_cwavef)
391 : if (type_calc == 2) then
392 : !$OMP TARGET UPDATE TO(ghc) IF(transfer_ghc)
393 : !$OMP TARGET UPDATE TO(gsc) IF(transfer_gsc .and. gs_ham%usepaw==1)
394 : end if
395 : #endif
396 : end if
397 :
398 : !============================================================
399 : ! Application of the local potential
400 : !============================================================
401 :
402 : ABI_NVTX_START_RANGE(NVTX_GETGHC_LOCPOT)
403 :
404 34965650 : if (any(type_calc == [0, 1, 3])) then
405 :
406 : ! Need a Vlocal
407 34962376 : ABI_CHECK(associated(gs_ham%vlocal), "We need vlocal in gs_ham!")
408 :
409 : ! fourwf can only process with one value of istwf_k
410 34962376 : if (gs_ham%use_gbt == 0) then
411 34823257 : ABI_CHECK(k1_eq_k2, 'vlocal (fourwf) cannot be computed with k/=k^prime!')
412 : end if
413 :
414 34962376 : nfft_blocks = 1;
415 34962376 : if(gs_ham%nfft_blocks > 1 .and. gs_ham%gpu_option/=ABI_GPU_DISABLED) then
416 0 : nfft_blocks = gs_ham%nfft_blocks
417 : end if
418 34962376 : chunk = ndat/nfft_blocks ! Divide by 2 to construct chunk of even number of bands
419 34962376 : residuchunk = ndat - nfft_blocks*chunk
420 :
421 : ! Eventually adjust load balancing for FFT (by changing FFT distrib)
422 : ! Not that have_to_reequilibrate can be true only if mpi_enreg%nproc_fft>1
423 34962376 : have_to_reequilibrate=.false.
424 34962376 : if (mpi_enreg%paral_kgb==1) then
425 919678 : ikpt_this_proc=bandfft_kpt_get_ikpt()
426 919678 : have_to_reequilibrate=bandfft_kpt(ikpt_this_proc)%have_to_reequilibrate
427 : end if
428 34962376 : ndat_ = ndat
429 34962376 : istwf_k_ = gs_ham%istwf_k
430 34962376 : double_rfft_trick = istwf_k_==2.and.ndat>1.and.mpi_enreg%paral_kgb==1.and.gs_ham%gpu_option==ABI_GPU_DISABLED
431 : ! LB-08-2024 : double_rfft_trick works only for paral_kgb=1, but I don't know why...
432 : ! Note that the trick can be activated only if nspinortot=1 (if =2 then istwf_k=1), so gs_ham%nvloc=1 too
433 : if (double_rfft_trick) then
434 16752 : ABI_CHECK(mpi_enreg%nproc_fft == 1, 'double_rfft_trick inside getghc is not implemented for npfft>1')
435 16752 : istwf_k_ = 1
436 16752 : ndat_ = ndat / 2
437 16752 : if (modulo(ndat,2)/=0) ndat_=ndat_+1
438 16752 : npw_fft=2*npw_k1
439 16752 : i0=1
440 16752 : if (mpi_enreg%me_g0_fft==1) then ! Do not include G=(0,0,0) twice
441 16752 : npw_fft=npw_fft-1
442 16752 : i0=2
443 : end if
444 50256 : ABI_MALLOC(kg_k_fft,(3,npw_fft))
445 50256 : ABI_MALLOC(cwavef_fft,(2,npw_fft*ndat_))
446 100676368 : kg_k_fft(:,1:npw_k1) = kg_k1(:,1:npw_k1)
447 100542352 : kg_k_fft(:,npw_k1+1:npw_fft) = -kg_k1(:,i0:npw_k1)
448 16752 : call cwavef_double_rfft_trick_pack(cwavef,cwavef_fft,mpi_enreg%me_g0_fft,ndat,npw_k1)
449 : end if
450 :
451 16752 : if (have_to_reequilibrate.and.double_rfft_trick) then
452 0 : ABI_ERROR("In getghc: have_to_reequilibrate cannot be activated with double_rfft_trick")
453 : end if
454 :
455 34962376 : if (have_to_reequilibrate) then
456 : ! Note: for this case we have ndat_=ndat
457 0 : npw_fft = bandfft_kpt(ikpt_this_proc)%npw_fft
458 0 : sendcount_fft => bandfft_kpt(ikpt_this_proc)%sendcount_fft(:)
459 0 : recvcount_fft => bandfft_kpt(ikpt_this_proc)%recvcount_fft(:)
460 0 : senddisp_fft => bandfft_kpt(ikpt_this_proc)%senddisp_fft(:)
461 0 : recvdisp_fft => bandfft_kpt(ikpt_this_proc)%recvdisp_fft(:)
462 0 : indices_pw_fft => bandfft_kpt(ikpt_this_proc)%indices_pw_fft(:)
463 0 : kg_k_fft => bandfft_kpt(ikpt_this_proc)%kg_k_fft(:,:)
464 0 : ABI_MALLOC(buff_wf,(2,npw_k1*ndat) )
465 0 : ABI_MALLOC(cwavef_fft,(2,npw_fft*ndat) )
466 0 : if(ndat>1) then
467 0 : ABI_MALLOC(cwavef_fft_tr, (2,npw_fft*ndat))
468 : end if
469 0 : do idat=1, ndat
470 0 : do ipw = 1 ,npw_k1
471 0 : buff_wf(1:2, idat + ndat*(indices_pw_fft(ipw)-1) ) = cwavef(1:2,ipw + npw_k1*(idat-1))
472 : end do
473 : end do
474 0 : if(ndat > 1) then
475 : call xmpi_alltoallv(buff_wf,2*ndat*sendcount_fft,2*ndat*senddisp_fft, &
476 0 : cwavef_fft_tr,2*ndat*recvcount_fft, 2*ndat*recvdisp_fft, mpi_enreg%comm_fft,ierr)
477 : ! We need to transpose data
478 0 : do idat=1,ndat
479 0 : do ipw = 1 ,npw_fft
480 0 : cwavef_fft(1:2, ipw + npw_fft*(idat-1)) = cwavef_fft_tr(1:2, idat + ndat*(ipw-1))
481 : end do
482 : end do
483 : else
484 : call xmpi_alltoallv(buff_wf,2*sendcount_fft,2*senddisp_fft, &
485 0 : cwavef_fft,2*recvcount_fft, 2*recvdisp_fft, mpi_enreg%comm_fft,ierr)
486 : end if
487 : end if
488 :
489 : ! Apply the local potential to the wavefunction
490 : ! Start from wavefunction in reciprocal space cwavef
491 : ! End with function ghc in reciprocal space also.
492 34962376 : fftalg = gs_ham%ngfft(7)
493 34962376 : if (gs_ham%gpu_option==ABI_GPU_DISABLED.and.fftalg/=401) then
494 171755270 : ABI_MALLOC(work,(2,gs_ham%n4,gs_ham%n5,gs_ham%n6))
495 611322 : else if(nfft_blocks==1) then
496 3056610 : ABI_MALLOC(work,(2,gs_ham%n4,gs_ham%n5,gs_ham%n6*ndat))
497 : else
498 0 : ABI_MALLOC(work,(2,gs_ham%n4,gs_ham%n5,gs_ham%n6*(chunk+residuchunk)))
499 : end if
500 : #ifdef HAVE_OPENMP_OFFLOAD
501 : !$OMP TARGET ENTER DATA MAP(alloc:work) IF(gs_ham%gpu_option==ABI_GPU_OPENMP)
502 : #endif
503 34962376 : weight=one
504 34962376 : if (.not.use_cwavef_r) then
505 34962376 : option_fft=2
506 34962376 : if (nspinortot==2) then
507 : ! Note: for this case we have ndat_=ndat
508 7488423 : ABI_MALLOC(cwavef1,(2,npw_k1*ndat))
509 4992282 : ABI_MALLOC(cwavef2,(2,npw_k1*ndat))
510 2496141 : if(gs_ham%gpu_option == ABI_GPU_OPENMP) then
511 : #ifdef HAVE_OPENMP_OFFLOAD
512 : !$OMP TARGET ENTER DATA MAP(alloc:cwavef1,cwavef2)
513 : !$OMP TARGET TEAMS DISTRIBUTE MAP(to:cwavef1,cwavef2,cwavef)
514 : do idat=1,ndat
515 : !$OMP PARALLEL DO COLLAPSE(2)
516 : do ipw=1,npw_k1
517 : do ig=1,2
518 : cwavef1(ig,ipw+(idat-1)*npw_k1)=cwavef(ig,ipw+(idat-1)*my_nspinor*npw_k1)
519 : cwavef2(ig,ipw+(idat-1)*npw_k1)=cwavef(ig,ipw+(idat-1)*my_nspinor*npw_k1+shift1)
520 : end do
521 : end do
522 : end do
523 : #endif
524 : else
525 5299641 : do idat=1,ndat
526 636002639 : do ipw=1,npw_k1
527 1892108994 : cwavef1(1:2,ipw+(idat-1)*npw_k1)=cwavef(1:2,ipw+(idat-1)*my_nspinor*npw_k1)
528 1894912494 : cwavef2(1:2,ipw+(idat-1)*npw_k1)=cwavef(1:2,ipw+(idat-1)*my_nspinor*npw_k1+shift1)
529 : end do
530 : end do
531 : end if
532 : end if
533 : else
534 0 : option_fft=3
535 0 : nfft_blocks=1
536 0 : if (nspinortot==2) then
537 0 : ABI_MALLOC(cwavef1,(0,0))
538 0 : ABI_MALLOC(cwavef2,(0,0))
539 : end if
540 : end if
541 :
542 34962376 : if (gs_ham%nvloc==1) then
543 : ! Treat scalar local potentials
544 :
545 32989271 : if (nspinortot==1) then
546 :
547 32466235 : if (use_cwavef_r) then
548 0 : do i3=1,n6
549 0 : do i2=1,n5
550 0 : do i1=1,n4
551 0 : work(1,i1,i2,i3) = gs_ham%vlocal(i1,i2,i3,1)*cwavef_r(1,i1,i2,i3,1)
552 0 : work(2,i1,i2,i3) = gs_ham%vlocal(i1,i2,i3,1)*cwavef_r(2,i1,i2,i3,1)
553 : end do
554 : end do
555 : end do
556 : end if
557 32466235 : if (have_to_reequilibrate.or.double_rfft_trick) then
558 : call fourwf(1,gs_ham%vlocal,cwavef_fft,cwavef_fft,work,gbound_k1,gbound_k2,&
559 : istwf_k_,kg_k_fft,kg_k_fft,gs_ham%mgfft,mpi_enreg,ndat_,gs_ham%ngfft,&
560 : npw_fft,npw_fft,gs_ham%n4,gs_ham%n5,gs_ham%n6,option_fft,tim_fourwf,&
561 16752 : weight,weight,gpu_option=gs_ham%gpu_option)
562 : else
563 : call fourwf_optmem(1,gs_ham%vlocal,cwavef,ghc,work,gbound_k1,gbound_k2,&
564 : istwf_k_,kg_k1,kg_k2,gs_ham%mgfft,mpi_enreg,ndat_,nfft_blocks,gs_ham%ngfft,&
565 : npw_k1,npw_k2,gs_ham%n4,gs_ham%n5,gs_ham%n6,option_fft,tim_fourwf,&
566 32449483 : weight,weight,gpu_option=gs_ham%gpu_option)
567 : end if
568 :
569 : else
570 : ! nspinortot==2
571 :
572 : ! Note: for this case we have ndat_=ndat
573 523036 : if (nspinor1TreatedByThisProc) then
574 519274 : if (use_cwavef_r) then
575 0 : do i3=1,n6
576 0 : do i2=1,n5
577 0 : do i1=1,n4
578 0 : work(1,i1,i2,i3) = gs_ham%vlocal(i1,i2,i3,1)*cwavef_r(1,i1,i2,i3,1)
579 0 : work(2,i1,i2,i3) = gs_ham%vlocal(i1,i2,i3,1)*cwavef_r(2,i1,i2,i3,1)
580 : end do
581 : end do
582 : end do
583 : #ifdef HAVE_OPENMP_OFFLOAD
584 : !$OMP TARGET UPDATE TO(work) IF(gs_ham%gpu_option==ABI_GPU_OPENMP)
585 : #endif
586 : end if
587 1557822 : ABI_MALLOC(ghc1,(2,npw_k2*ndat))
588 : #ifdef HAVE_OPENMP_OFFLOAD
589 : !$OMP TARGET ENTER DATA MAP(alloc:ghc1) IF(gs_ham%gpu_option==ABI_GPU_OPENMP)
590 : #endif
591 : call fourwf_optmem(1,gs_ham%vlocal,cwavef1,ghc1,work,gbound_k1,gbound_k2,&
592 : istwf_k_,kg_k1,kg_k2,gs_ham%mgfft,mpi_enreg,ndat,nfft_blocks,gs_ham%ngfft,&
593 : npw_k1,npw_k2,gs_ham%n4,gs_ham%n5,gs_ham%n6,option_fft,tim_fourwf,&
594 519274 : weight,weight,gpu_option=gs_ham%gpu_option)
595 519274 : if(gs_ham%gpu_option==ABI_GPU_OPENMP) then
596 : #ifdef HAVE_OPENMP_OFFLOAD
597 : !$OMP TARGET TEAMS DISTRIBUTE MAP(to:ghc,ghc1)
598 : do idat=1,ndat
599 : !$OMP PARALLEL DO COLLAPSE(2)
600 : do ipw =1, npw_k2
601 : do ig =1,2
602 : ghc(ig,ipw+(idat-1)*my_nspinor*npw_k2)=ghc1(ig,ipw+(idat-1)*npw_k2)
603 : end do
604 : end do
605 : end do
606 : #endif
607 : else
608 1344221 : do idat=1,ndat
609 258114800 : do ipw =1, npw_k2
610 771136684 : ghc(1:2,ipw+(idat-1)*my_nspinor*npw_k2)=ghc1(1:2,ipw+(idat-1)*npw_k2)
611 : end do
612 : end do
613 : end if
614 : #ifdef HAVE_OPENMP_OFFLOAD
615 : !$OMP TARGET EXIT DATA MAP(delete:ghc1) IF(gs_ham%gpu_option==ABI_GPU_OPENMP)
616 : #endif
617 519274 : ABI_FREE(ghc1)
618 : end if ! spin 1 treated by this proc
619 :
620 523036 : if (nspinor2TreatedByThisProc) then
621 519274 : if (use_cwavef_r) then
622 0 : do i3=1,n6
623 0 : do i2=1,n5
624 0 : do i1=1,n4
625 0 : work(1,i1,i2,i3) = gs_ham%vlocal(i1,i2,i3,1)*cwavef_r(1,i1,i2,i3,2)
626 0 : work(2,i1,i2,i3) = gs_ham%vlocal(i1,i2,i3,1)*cwavef_r(2,i1,i2,i3,2)
627 : end do
628 : end do
629 : end do
630 : end if
631 1557822 : ABI_MALLOC(ghc2,(2,npw_k2*ndat))
632 : #ifdef HAVE_OPENMP_OFFLOAD
633 : !$OMP TARGET ENTER DATA MAP(alloc:ghc2) IF(gs_ham%gpu_option==ABI_GPU_OPENMP)
634 : #endif
635 : call fourwf_optmem(1,gs_ham%vlocal,cwavef2,ghc2,work,gbound_k1,gbound_k2,&
636 : istwf_k_,kg_k1,kg_k2,gs_ham%mgfft,mpi_enreg,ndat,nfft_blocks,gs_ham%ngfft,&
637 : npw_k1,npw_k2,gs_ham%n4,gs_ham%n5,gs_ham%n6,option_fft,tim_fourwf,weight,weight,&
638 519274 : gpu_option=gs_ham%gpu_option)
639 :
640 519274 : if(gs_ham%gpu_option==ABI_GPU_OPENMP) then
641 : #ifdef HAVE_OPENMP_OFFLOAD
642 : !$OMP TARGET TEAMS DISTRIBUTE MAP(to:ghc,ghc2)
643 : do idat=1,ndat
644 : !$OMP PARALLEL DO COLLAPSE(2)
645 : do ipw=1,npw_k2
646 : do ig =1,2
647 : ghc(ig,ipw+(idat-1)*my_nspinor*npw_k2+shift2)=ghc2(ig,ipw+(idat-1)*npw_k2)
648 : end do
649 : end do
650 : end do
651 : #endif
652 : else
653 1344221 : do idat=1,ndat
654 258114800 : do ipw=1,npw_k2
655 771136684 : ghc(1:2,ipw+(idat-1)*my_nspinor*npw_k2+shift2)=ghc2(1:2,ipw+(idat-1)*npw_k2)
656 : end do
657 : end do
658 : end if
659 : #ifdef HAVE_OPENMP_OFFLOAD
660 : !$OMP TARGET EXIT DATA MAP(delete:ghc2) IF(gs_ham%gpu_option==ABI_GPU_OPENMP)
661 : #endif
662 519274 : ABI_FREE(ghc2)
663 : end if ! spin 2 treated by this proc
664 :
665 : end if ! nspinortot
666 :
667 1973105 : else if (gs_ham%nvloc==4) then
668 : ! Treat non-collinear local potentials
669 : ! Note: for this case we have ndat_=ndat
670 5919315 : ABI_MALLOC(ghc1,(2,npw_k2*ndat))
671 3946210 : ABI_MALLOC(ghc2,(2,npw_k2*ndat))
672 3946210 : ABI_MALLOC(ghc3,(2,npw_k2*ndat))
673 3946210 : ABI_MALLOC(ghc4,(2,npw_k2*ndat))
674 1973105 : if(gs_ham%gpu_option == ABI_GPU_OPENMP) then
675 : #ifdef HAVE_OPENMP_OFFLOAD
676 : !$OMP TARGET ENTER DATA MAP(alloc:ghc1,ghc2,ghc3,ghc4)
677 : call gpu_set_to_zero(ghc1, int(2,c_size_t)*npw_k2*ndat)
678 : call gpu_set_to_zero(ghc2, int(2,c_size_t)*npw_k2*ndat)
679 : call gpu_set_to_zero(ghc3, int(2,c_size_t)*npw_k2*ndat)
680 : call gpu_set_to_zero(ghc4, int(2,c_size_t)*npw_k2*ndat)
681 : #endif
682 : else
683 4430500181 : ghc1(:,:)=zero; ghc2(:,:)=zero; ghc3(:,:)=zero ; ghc4(:,:)=zero
684 : end if
685 1973105 : if (use_cwavef_r) then
686 0 : ABI_MALLOC(vlocal_tmp,(0,0,0))
687 : else
688 9865525 : ABI_MALLOC(vlocal_tmp,(gs_ham%n4,gs_ham%n5,gs_ham%n6))
689 : end if
690 : ! ghc1=v11*phi1
691 1973105 : if (nspinor1TreatedByThisProc) then
692 1951185 : if (use_cwavef_r) then
693 0 : do i3=1,n6
694 0 : do i2=1,n5
695 0 : do i1=1,n4
696 0 : work(1,i1,i2,i3) = gs_ham%vlocal(i1,i2,i3,1)*cwavef_r(1,i1,i2,i3,1)
697 0 : work(2,i1,i2,i3) = gs_ham%vlocal(i1,i2,i3,1)*cwavef_r(2,i1,i2,i3,1)
698 : end do
699 : end do
700 : end do
701 : #ifdef HAVE_OPENMP_OFFLOAD
702 : !$OMP TARGET UPDATE TO(work) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
703 : #endif
704 : else
705 : ! LB,07/22:
706 : ! Weird segmentation fault encountered here if called with multithreaded_getghc for big systems.
707 : ! Using an explicit loop instead of fortran syntax seems to solve the problem, I don't understand why...
708 : !vlocal_tmp(:,:,:)=gs_ham%vlocal(:,:,:,1)
709 33265230 : do i3=1,n6
710 570470291 : do i2=1,n5
711 10235254527 : do i1=1,n4
712 10203940482 : vlocal_tmp(i1,i2,i3) = gs_ham%vlocal(i1,i2,i3,1)
713 : end do
714 : end do
715 : end do
716 : end if
717 : call fourwf_optmem(1,vlocal_tmp,cwavef1,ghc1,work,gbound_k1,gbound_k2,&
718 : istwf_k_,kg_k1,kg_k2,gs_ham%mgfft,mpi_enreg,ndat,nfft_blocks,gs_ham%ngfft,&
719 : npw_k1,npw_k2,gs_ham%n4,gs_ham%n5,gs_ham%n6,option_fft,tim_fourwf,weight,weight,&
720 1951185 : gpu_option=gs_ham%gpu_option)
721 : end if
722 : ! ghc2=v22*phi2
723 1973105 : if (nspinor2TreatedByThisProc) then
724 1951185 : if (use_cwavef_r) then
725 0 : do i3=1,n6
726 0 : do i2=1,n5
727 0 : do i1=1,n4
728 0 : work(1,i1,i2,i3) = gs_ham%vlocal(i1,i2,i3,2)*cwavef_r(1,i1,i2,i3,2)
729 0 : work(2,i1,i2,i3) = gs_ham%vlocal(i1,i2,i3,2)*cwavef_r(2,i1,i2,i3,2)
730 : end do
731 : end do
732 : end do
733 : #ifdef HAVE_OPENMP_OFFLOAD
734 : !$OMP TARGET UPDATE TO(work) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
735 : #endif
736 : else
737 : ! LB,07/22:
738 : ! Weird segmentation fault encountered here if called with multithreaded_getghc for big systems.
739 : ! Using an explicit loop instead of fortran syntax seems to solve the problem, I don't understand why...
740 : !vlocal_tmp(:,:,:)=gs_ham%vlocal(:,:,:,2)
741 33265230 : do i3=1,n6
742 570470291 : do i2=1,n5
743 10235254527 : do i1=1,n4
744 10203940482 : vlocal_tmp(i1,i2,i3) = gs_ham%vlocal(i1,i2,i3,2)
745 : end do
746 : end do
747 : end do
748 : #ifdef HAVE_OPENMP_OFFLOAD
749 : !$OMP TARGET UPDATE TO(work) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
750 : #endif
751 : end if
752 : call fourwf_optmem(1,vlocal_tmp,cwavef2,ghc2,work,gbound_k1,gbound_k2,&
753 : istwf_k_,kg_k1,kg_k2,gs_ham%mgfft,mpi_enreg,ndat,nfft_blocks,gs_ham%ngfft,&
754 : npw_k1,npw_k2,gs_ham%n4,gs_ham%n5,gs_ham%n6,option_fft,tim_fourwf,weight,weight,&
755 1951185 : gpu_option=gs_ham%gpu_option)
756 : end if
757 1973105 : ABI_FREE(vlocal_tmp)
758 1973105 : cplex=2
759 1973105 : if (use_cwavef_r) then
760 0 : ABI_MALLOC(vlocal_tmp,(0,0,0))
761 : else
762 9865525 : ABI_MALLOC(vlocal_tmp,(cplex*gs_ham%n4,gs_ham%n5,gs_ham%n6))
763 : end if
764 : ! ghc3=(re(v12)-im(v12))*phi1
765 1973105 : if (nspinor1TreatedByThisProc) then
766 1951185 : if (use_cwavef_r) then
767 0 : do i3=1,n6
768 0 : do i2=1,n5
769 0 : do i1=1,n4
770 0 : work(1,i1,i2,i3)= gs_ham%vlocal(i1,i2,i3,3)*cwavef_r(1,i1,i2,i3,1)+gs_ham%vlocal(i1,i2,i3,4)*cwavef_r(2,i1,i2,i3,1)
771 0 : work(2,i1,i2,i3)=-gs_ham%vlocal(i1,i2,i3,4)*cwavef_r(1,i1,i2,i3,1)+gs_ham%vlocal(i1,i2,i3,3)*cwavef_r(2,i1,i2,i3,1)
772 : end do
773 : end do
774 : end do
775 : #ifdef HAVE_OPENMP_OFFLOAD
776 : !$OMP TARGET UPDATE TO(work) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
777 : #endif
778 : else
779 33265230 : do i3=1,gs_ham%n6
780 570470291 : do i2=1,gs_ham%n5
781 10235254527 : do i1=1,gs_ham%n4
782 9666735421 : vlocal_tmp(2*i1-1,i2,i3)= gs_ham%vlocal(i1,i2,i3,3)
783 10203940482 : vlocal_tmp(2*i1 ,i2,i3)=-gs_ham%vlocal(i1,i2,i3,4)
784 : end do
785 : end do
786 : end do
787 : end if
788 : call fourwf_optmem(cplex,vlocal_tmp,cwavef1,ghc3,work,gbound_k1,gbound_k2,&
789 : istwf_k_,kg_k1,kg_k2,gs_ham%mgfft,mpi_enreg,ndat,nfft_blocks,gs_ham%ngfft,&
790 : npw_k1,npw_k2,gs_ham%n4,gs_ham%n5,gs_ham%n6,option_fft,tim_fourwf,weight,weight,&
791 1951185 : gpu_option=gs_ham%gpu_option)
792 : end if
793 : ! ghc4=(re(v12)+im(v12))*phi2
794 1973105 : if (nspinor2TreatedByThisProc) then
795 1951185 : if (use_cwavef_r) then
796 0 : do i3=1,n6
797 0 : do i2=1,n5
798 0 : do i1=1,n4
799 0 : work(1,i1,i2,i3)= gs_ham%vlocal(i1,i2,i3,3)*cwavef_r(1,i1,i2,i3,2)-gs_ham%vlocal(i1,i2,i3,4)*cwavef_r(2,i1,i2,i3,2)
800 0 : work(2,i1,i2,i3)= gs_ham%vlocal(i1,i2,i3,4)*cwavef_r(1,i1,i2,i3,2)+gs_ham%vlocal(i1,i2,i3,3)*cwavef_r(2,i1,i2,i3,2)
801 : end do
802 : end do
803 : end do
804 : #ifdef HAVE_OPENMP_OFFLOAD
805 : !$OMP TARGET UPDATE TO(work) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
806 : #endif
807 : else
808 33265230 : do i3=1,gs_ham%n6
809 570470291 : do i2=1,gs_ham%n5
810 10235254527 : do i1=1,gs_ham%n4
811 9666735421 : vlocal_tmp(2*i1-1,i2,i3)= gs_ham%vlocal(i1,i2,i3,3)
812 10203940482 : vlocal_tmp(2*i1 ,i2,i3)= gs_ham%vlocal(i1,i2,i3,4)
813 : end do
814 : end do
815 : end do
816 : end if
817 : call fourwf_optmem(cplex,vlocal_tmp,cwavef2,ghc4,work,gbound_k1,gbound_k2,&
818 : istwf_k_,kg_k1,kg_k2,gs_ham%mgfft,mpi_enreg,ndat,nfft_blocks,gs_ham%ngfft,&
819 : npw_k1,npw_k2,gs_ham%n4,gs_ham%n5,gs_ham%n6,option_fft,tim_fourwf,weight,weight,&
820 1951185 : gpu_option=gs_ham%gpu_option)
821 : end if
822 1973105 : ABI_FREE(vlocal_tmp)
823 : ! Build ghc from pieces
824 : ! (v11,v22,Re(v12)+iIm(v12);Re(v12)-iIm(v12))(psi1;psi2): matrix product
825 1973105 : if (mpi_enreg%paral_spinor==0) then
826 1929265 : if(gs_ham%gpu_option == ABI_GPU_OPENMP) then
827 : #ifdef HAVE_OPENMP_OFFLOAD
828 : !$OMP TARGET TEAMS DISTRIBUTE MAP(to:ghc,ghc1,ghc2,ghc3,ghc4)
829 : do idat=1,ndat
830 : !$OMP PARALLEL DO
831 : do ipw=1,npw_k2
832 : ghc(1,ipw+(idat-1)*my_nspinor*npw_k2) =ghc1(1,ipw+(idat-1)*npw_k2)+ghc4(1,ipw+(idat-1)*npw_k2)
833 : ghc(2,ipw+(idat-1)*my_nspinor*npw_k2) =ghc1(2,ipw+(idat-1)*npw_k2)+ghc4(2,ipw+(idat-1)*npw_k2)
834 : ghc(1,ipw+(idat-1)*my_nspinor*npw_k2+shift2)=ghc3(1,ipw+(idat-1)*npw_k2)+ghc2(1,ipw+(idat-1)*npw_k2)
835 : ghc(2,ipw+(idat-1)*my_nspinor*npw_k2+shift2)=ghc3(2,ipw+(idat-1)*npw_k2)+ghc2(2,ipw+(idat-1)*npw_k2)
836 : end do
837 : end do
838 : #endif
839 : else
840 3858530 : do idat=1,ndat
841 363120213 : do ipw=1,npw_k2
842 1077785049 : ghc(1:2,ipw+(idat-1)*my_nspinor*npw_k2) =ghc1(1:2,ipw+(idat-1)*npw_k2)+ghc4(1:2,ipw+(idat-1)*npw_k2)
843 1079714314 : ghc(1:2,ipw+(idat-1)*my_nspinor*npw_k2+shift2)=ghc3(1:2,ipw+(idat-1)*npw_k2)+ghc2(1:2,ipw+(idat-1)*npw_k2)
844 : end do
845 : end do
846 : end if
847 : else
848 43840 : call xmpi_sum(ghc4,mpi_enreg%comm_spinor,ierr)
849 43840 : call xmpi_sum(ghc3,mpi_enreg%comm_spinor,ierr)
850 43840 : if(gs_ham%gpu_option == ABI_GPU_OPENMP) then
851 : #ifdef HAVE_OPENMP_OFFLOAD
852 : if (nspinor1TreatedByThisProc) then
853 : !$OMP TARGET TEAMS DISTRIBUTE MAP(to:ghc,ghc1,ghc4)
854 : do idat=1,ndat
855 : !$OMP PARALLEL DO
856 : do ipw=1,npw_k2
857 : ghc(1,ipw+(idat-1)*my_nspinor*npw_k2)=ghc1(1,ipw+(idat-1)*npw_k2)+ghc4(1,ipw+(idat-1)*npw_k2)
858 : ghc(2,ipw+(idat-1)*my_nspinor*npw_k2)=ghc1(2,ipw+(idat-1)*npw_k2)+ghc4(2,ipw+(idat-1)*npw_k2)
859 : end do
860 : end do
861 : else if (nspinor2TreatedByThisProc) then
862 : !$OMP TARGET TEAMS DISTRIBUTE MAP(to:ghc,ghc2,ghc3)
863 : do idat=1,ndat
864 : !$OMP PARALLEL DO
865 : do ipw=1,npw_k2
866 : ghc(1,ipw+(idat-1)*my_nspinor*npw_k2+shift2)=ghc3(1,ipw+(idat-1)*npw_k2)+ghc2(1,ipw+(idat-1)*npw_k2)
867 : ghc(2,ipw+(idat-1)*my_nspinor*npw_k2+shift2)=ghc3(2,ipw+(idat-1)*npw_k2)+ghc2(2,ipw+(idat-1)*npw_k2)
868 : end do
869 : end do
870 : end if
871 : #endif
872 : else
873 43840 : if (nspinor1TreatedByThisProc) then
874 43840 : do idat=1,ndat
875 4934960 : do ipw=1,npw_k2
876 14695280 : ghc(1:2,ipw+(idat-1)*my_nspinor*npw_k2)=ghc1(1:2,ipw+(idat-1)*npw_k2)+ghc4(1:2,ipw+(idat-1)*npw_k2)
877 : end do
878 : end do
879 21920 : else if (nspinor2TreatedByThisProc) then
880 43840 : do idat=1,ndat
881 4934960 : do ipw=1,npw_k2
882 14695280 : ghc(1:2,ipw+(idat-1)*my_nspinor*npw_k2+shift2)=ghc3(1:2,ipw+(idat-1)*npw_k2)+ghc2(1:2,ipw+(idat-1)*npw_k2)
883 : end do
884 : end do
885 : end if
886 : end if
887 : end if
888 : #ifdef HAVE_OPENMP_OFFLOAD
889 : !$OMP TARGET EXIT DATA MAP(delete:ghc1,ghc2,ghc3,ghc4) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
890 : #endif
891 1973105 : ABI_FREE(ghc1)
892 1973105 : ABI_FREE(ghc2)
893 1973105 : ABI_FREE(ghc3)
894 1973105 : ABI_FREE(ghc4)
895 : end if ! nvloc
896 :
897 34962376 : if (nspinortot==2) then
898 : #ifdef HAVE_OPENMP_OFFLOAD
899 : !$OMP TARGET EXIT DATA MAP(delete:cwavef1,cwavef2) IF (gs_ham%gpu_option == ABI_GPU_OPENMP .and. .not.use_cwavef_r)
900 : #endif
901 2496141 : ABI_FREE(cwavef1)
902 2496141 : ABI_FREE(cwavef2)
903 : end if
904 :
905 : #ifdef HAVE_OPENMP_OFFLOAD
906 : !$OMP TARGET EXIT DATA MAP(delete:work) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
907 : #endif
908 34962376 : ABI_FREE(work)
909 :
910 34962376 : if (double_rfft_trick) then
911 16752 : call cwavef_double_rfft_trick_unpack(ghc,cwavef_fft,mpi_enreg%me_g0_fft,ndat,npw_k1)
912 16752 : ABI_FREE(kg_k_fft)
913 16752 : ABI_FREE(cwavef_fft)
914 : end if
915 :
916 : ! Retrieve eventually original FFT distrib
917 34962376 : if(have_to_reequilibrate) then
918 : ! Note: for this case we have ndat_=ndat
919 0 : if(ndat > 1 ) then
920 0 : do idat=1,ndat
921 0 : do ipw = 1 ,npw_fft
922 0 : cwavef_fft_tr(1:2, idat + ndat*(ipw-1)) = cwavef_fft(1:2, ipw + npw_fft*(idat-1))
923 : end do
924 : end do
925 : call xmpi_alltoallv(cwavef_fft_tr,2*ndat*recvcount_fft, 2*ndat*recvdisp_fft, &
926 0 : buff_wf,2*ndat*sendcount_fft,2*ndat*senddisp_fft, mpi_enreg%comm_fft,ierr)
927 : else
928 : call xmpi_alltoallv(cwavef_fft,2*recvcount_fft, 2*recvdisp_fft, &
929 0 : buff_wf,2*sendcount_fft,2*senddisp_fft, mpi_enreg%comm_fft,ierr)
930 : end if
931 0 : do idat=1,ndat
932 0 : do ipw = 1 ,npw_k2
933 0 : ghc(1:2,ipw + npw_k2*(idat-1)) = buff_wf(1:2, idat + ndat*(indices_pw_fft(ipw)-1))
934 : end do
935 : end do
936 0 : ABI_FREE(buff_wf)
937 0 : ABI_FREE(cwavef_fft)
938 0 : if(ndat > 1) then
939 0 : ABI_FREE(cwavef_fft_tr)
940 : end if
941 : end if
942 :
943 : ! Add metaGGA contribution
944 34962376 : if (associated(gs_ham%vxctaulocal)) then
945 90464 : ABI_CHECK(k1_eq_k2, 'metaGGA not allowed for k/=k_^prime!')
946 542784 : ABI_CHECK_IEQ(size(gs_ham%vxctaulocal), gs_ham%n4*gs_ham%n5*gs_ham%n6*gs_ham%nvloc*4, 'wrong sizes for vxctaulocal!')
947 :
948 271392 : ABI_MALLOC(ghc_mGGA,(2,npw_k1*my_nspinor*ndat))
949 : #ifdef HAVE_OPENMP_OFFLOAD
950 : !$OMP TARGET UPDATE FROM(cwavef) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
951 : #endif
952 90464 : if (double_rfft_trick) then
953 480 : ABI_MALLOC(kg_k_fft,(3,npw_fft))
954 480 : ABI_MALLOC(cwavef_fft,(2,npw_fft*ndat_))
955 320 : ABI_MALLOC(ghc_mGGA_fft,(2,npw_fft*ndat_))
956 413600 : kg_k_fft(:,1:npw_k1) = kg_k1(:,1:npw_k1)
957 412320 : kg_k_fft(:,npw_k1+1:npw_fft) = -kg_k1(:,i0:npw_k1)
958 160 : call cwavef_double_rfft_trick_pack(cwavef,cwavef_fft,mpi_enreg%me_g0_fft,ndat,npw_k1)
959 : call getghc_mGGA(cwavef_fft,ghc_mGGA_fft,gbound_k1,gs_ham%gprimd,istwf_k_,kg_k_fft,kpt_k1,&
960 : & gs_ham%mgfft,mpi_enreg,ndat_,gs_ham%ngfft,npw_fft,gs_ham%nvloc,&
961 160 : & gs_ham%n4,gs_ham%n5,gs_ham%n6,my_nspinor,gs_ham%vxctaulocal,gs_ham%gpu_option)
962 160 : call cwavef_double_rfft_trick_unpack(ghc_mGGA,ghc_mGGA_fft,mpi_enreg%me_g0_fft,ndat,npw_k1)
963 160 : ABI_FREE(kg_k_fft)
964 160 : ABI_FREE(cwavef_fft)
965 160 : ABI_FREE(ghc_mGGA_fft)
966 : else
967 : call getghc_mGGA(cwavef,ghc_mGGA,gbound_k1,gs_ham%gprimd,istwf_k_,kg_k1,kpt_k1,&
968 : & gs_ham%mgfft,mpi_enreg,ndat,gs_ham%ngfft,npw_k1,gs_ham%nvloc,&
969 90304 : & gs_ham%n4,gs_ham%n5,gs_ham%n6,my_nspinor,gs_ham%vxctaulocal,gs_ham%gpu_option)
970 : end if
971 : #ifdef HAVE_OPENMP_OFFLOAD
972 : !$OMP TARGET UPDATE FROM(ghc) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
973 : #endif
974 : !LB-2025-12-16: intel19 crashes here when npw_k1 is too big. A solution is to write the loop explicitely
975 : !ghc(1:2,1:npw_k2*my_nspinor*ndat)=ghc(1:2,1:npw_k2*my_nspinor*ndat)+ghc_mGGA(1:2,1:npw_k2*my_nspinor*ndat)
976 56805312 : do idat=1,npw_k1*my_nspinor*ndat
977 170235008 : do ig=1,2
978 170144544 : ghc(ig,idat)=ghc(ig,idat)+ghc_mGGA(ig,idat)
979 : end do
980 : end do
981 : #ifdef HAVE_OPENMP_OFFLOAD
982 : !$OMP TARGET UPDATE TO(ghc) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
983 : #endif
984 90464 : ABI_FREE(ghc_mGGA)
985 : end if
986 :
987 : ! Add nuclear dipole moment contribution
988 34962376 : if (associated(gs_ham%vectornd)) then
989 673202 : ABI_CHECK(k1_eq_k2, 'nuclear dipole vector potential not allowed for k/=k_^prime!')
990 4039212 : if (size(gs_ham%vectornd)/=gs_ham%n4*gs_ham%n5*gs_ham%n6*gs_ham%nvloc*3) then
991 0 : ABI_BUG('wrong sizes for vectornd in getghc!')
992 : end if
993 2019606 : ABI_MALLOC(ghc_vectornd,(2,npw_k1*my_nspinor*ndat))
994 939408950 : ghc_vectornd=zero
995 : #ifdef HAVE_OPENMP_OFFLOAD
996 : !$OMP TARGET UPDATE FROM(cwavef) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
997 : #endif
998 : call getghc_nucdip(cwavef,ghc_vectornd,gbound_k1,istwf_k_,kg_k1,kpt_k1,&
999 : gs_ham%mgfft,mpi_enreg,ndat,gs_ham%ngfft,npw_k1,gs_ham%nvloc,&
1000 673202 : gs_ham%n4,gs_ham%n5,gs_ham%n6,my_nspinor,gs_ham%vectornd,gs_ham%vlocal,gs_ham%zora,gs_ham%gpu_option)
1001 :
1002 : #ifdef HAVE_OPENMP_OFFLOAD
1003 : !$OMP TARGET UPDATE FROM(ghc) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
1004 : #endif
1005 : !LB-2025-12-16: intel19 crashes here when npw_k1 is too big. A solution is to write the loop explicitely
1006 : !ghc(1:2,1:npw_k2*my_nspinor*ndat)=ghc(1:2,1:npw_k2*my_nspinor*ndat)+ghc_vectornd(1:2,1:npw_k2*my_nspinor*ndat)
1007 313585118 : do idat=1,npw_k1*my_nspinor*ndat
1008 939408950 : do ig=1,2
1009 938735748 : ghc(ig,idat)=ghc(ig,idat)+ghc_vectornd(ig,idat)
1010 : end do
1011 : end do
1012 : #ifdef HAVE_OPENMP_OFFLOAD
1013 : !$OMP TARGET UPDATE TO(ghc) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
1014 : #endif
1015 :
1016 673202 : ABI_FREE(ghc_vectornd)
1017 : end if
1018 :
1019 : ! If only local part is applied, still we have to filter the result because of dilatmx.
1020 : ! Otherwise it is done when adding kinetic term.
1021 34962376 : if (type_calc==1.and.filter_dilatmx_loc_) then
1022 :
1023 204650 : ABI_CHECK(gs_ham%use_gbt == 0, "use_gbt not coded!")
1024 :
1025 204650 : if(gs_ham%gpu_option == ABI_GPU_OPENMP) then
1026 : #ifdef HAVE_OPENMP_OFFLOAD
1027 : !$OMP TARGET TEAMS DISTRIBUTE MAP(to:ghc,kinpw_k2)
1028 : do idat=1,ndat
1029 : !$OMP PARALLEL DO PRIVATE(igspinor) COLLAPSE(2)
1030 : do ispinor=1,my_nspinor
1031 : do ig=1,npw_k2
1032 : igspinor=ig+npw_k2*(ispinor-1)+npw_k2*my_nspinor*(idat-1)
1033 : if(kinpw_k2(ig)>hugevalue) ghc(:,igspinor)=zero
1034 : end do ! ig
1035 : end do ! ispinor
1036 : end do
1037 : #endif
1038 : else
1039 1014410 : do idat=1,ndat
1040 : !$OMP PARALLEL DO PRIVATE(igspinor) COLLAPSE(2) IF(gemm_nonlop_use_gemm)
1041 2016282 : do ispinor=1,my_nspinor
1042 125631396 : do ig=1,npw_k2
1043 123819764 : igspinor=ig+npw_k2*(ispinor-1)+npw_k2*my_nspinor*(idat-1)
1044 129219672 : if(kinpw_k2(ig)>hugevalue) ghc(:,igspinor)=zero
1045 : end do ! ig
1046 : end do ! ispinor
1047 : end do
1048 : end if
1049 : end if
1050 :
1051 : end if ! type_calc
1052 :
1053 : ABI_NVTX_END_RANGE()
1054 :
1055 34965650 : if (any(type_calc == [0, 2, 3])) then
1056 : !============================================================
1057 : ! Application of the non-local potential and the Fock potential
1058 : !============================================================
1059 :
1060 : ABI_NVTX_START_RANGE(NVTX_GETGHC_NLOCPOT)
1061 :
1062 34757726 : if (type_calc==0 .or. type_calc==2) then
1063 34757726 : signs=2 ; choice=1 ; nnlout=1 ; idir=0 ; tim_nonlop=1
1064 34757726 : cpopt_here=-1;if (gs_ham%usepaw==1) cpopt_here=cpopt
1065 34757726 : if (has_fock) then
1066 142256 : if (gs_ham%usepaw==1) then
1067 13114 : cpopt_here=max(cpopt,0)
1068 13114 : if (cpopt<2) then
1069 91798 : ABI_MALLOC(cwaveprj_fock,(gs_ham%natom,my_nspinor*ndat))
1070 39342 : ABI_MALLOC(dimcprj,(gs_ham%natom))
1071 13114 : call pawcprj_getdim(dimcprj,gs_ham%natom,gs_ham%nattyp,gs_ham%ntypat,gs_ham%typat,fock%pawtab,'O')
1072 13114 : call pawcprj_alloc(cwaveprj_fock,0,dimcprj)
1073 13114 : ABI_FREE(dimcprj)
1074 : else
1075 0 : cwaveprj_fock=>cwaveprj
1076 : end if
1077 13114 : cwaveprj_nonlop=>cwaveprj_fock
1078 : else
1079 129142 : cwaveprj_nonlop=>cwaveprj
1080 129142 : cwaveprj_fock=>cwaveprj
1081 : end if
1082 : else
1083 34615470 : cwaveprj_nonlop=>cwaveprj
1084 : end if
1085 34757726 : paw_opt=gs_ham%usepaw ; if (sij_opt/=0) paw_opt=sij_opt+3
1086 70970152 : lambda_ndat = lambda
1087 :
1088 34757726 : if (gs_ham%use_gbt == 0) then
1089 34618607 : if (gs_ham%usepaw==0) gsc_ptr => nonlop_dum
1090 34618607 : if (gs_ham%usepaw==1) gsc_ptr => gsc
1091 :
1092 : call nonlop(choice,cpopt_here,cwaveprj_nonlop,enlout,gs_ham,idir,lambda_ndat,mpi_enreg,ndat,&
1093 34618607 : nnlout,paw_opt,signs,gsc_ptr,tim_nonlop,cwavef,gvnlxc_,select_k=select_k_)
1094 : else
1095 : ! GBT case. Treat up and down components separately.
1096 139119 : gs_ham%nspinor = 1
1097 :
1098 : ! Split cwavef and gvnlxc
1099 417357 : ABI_MALLOC(cwavef_spin, (2, npw_k1*ndat))
1100 278238 : ABI_MALLOC(gvnlxc_spin, (2, npw_k1*ndat))
1101 :
1102 139119 : if (gs_ham%usepaw==0) gsc_ptr => nonlop_dum
1103 139119 : if (gs_ham%usepaw==1) gsc_ptr => gsc
1104 :
1105 : ! Apply Vnl{k-q/2} to u^up
1106 139119 : gs_ham%ispin_gbt = 1
1107 139119 : call cg_copy_spin(1, npw_k1, nspinortot, ndat, cwavef, cwavef_spin)
1108 : call nonlop(choice, cpopt_here, cwaveprj_nonlop, enlout, gs_ham, idir, lambda_ndat, mpi_enreg, ndat, &
1109 139119 : nnlout, paw_opt, signs, gsc_ptr, tim_nonlop, cwavef_spin, gvnlxc_spin, select_k=K_H_K)
1110 : ! Insert results in the right position.
1111 139119 : call cg_put_spin(1, npw_k1, nspinortot, ndat, gvnlxc_spin, gvnlxc_)
1112 :
1113 : ! Apply H_{k+q/2} to u^down
1114 : !gvnlxc_spin = zero
1115 139119 : gs_ham%ispin_gbt = 2
1116 139119 : call cg_copy_spin(2, npw_k1, nspinortot, ndat, cwavef, cwavef_spin)
1117 : call nonlop(choice, cpopt_here, cwaveprj_nonlop, enlout, gs_ham, idir, lambda_ndat, mpi_enreg, ndat, &
1118 139119 : nnlout, paw_opt, signs, gsc_ptr, tim_nonlop, cwavef_spin, gvnlxc_spin, select_k=KPRIME_H_KPRIME)
1119 : ! Insert results in the right position.
1120 139119 : call cg_put_spin(2, npw_k1, nspinortot, ndat, gvnlxc_spin, gvnlxc_)
1121 :
1122 139119 : gs_ham%nspinor = 2
1123 139119 : ABI_FREE(cwavef_spin)
1124 139119 : ABI_FREE(gvnlxc_spin)
1125 : end if ! use_gbt
1126 :
1127 34757726 : if (gs_ham%usepaw==1 .and. has_fock)then
1128 13114 : if (fock_get_getghc_call(fock)==1) then
1129 13114 : if(gs_ham%gpu_option==ABI_GPU_KOKKOS) then
1130 : #if defined HAVE_GPU && defined HAVE_YAKL
1131 : ABI_MALLOC_MANAGED(gvnlc, (/2,npw_k2*my_nspinor*ndat/))
1132 : #endif
1133 : else
1134 39342 : ABI_MALLOC(gvnlc, (2,npw_k2*my_nspinor*ndat))
1135 : #if defined HAVE_OPENMP_OFFLOAD
1136 : !$OMP TARGET ENTER DATA MAP(to:gvnlc) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
1137 : #endif
1138 : end if
1139 13114 : if(gs_ham%gpu_option==ABI_GPU_OPENMP) then
1140 0 : call gpu_copy(gvnlc, gvnlxc_, int(2,c_size_t)*npw_k2*my_nspinor*ndat)
1141 : else
1142 48885164 : gvnlc=gvnlxc_
1143 : end if
1144 : endif
1145 : endif
1146 :
1147 : ! Calculation of the Fock exact exchange contribution from the Fock or ACE operator
1148 26152392 : if (has_fock) then
1149 142256 : if (fock_get_getghc_call(fock)==1) then
1150 : if (gs_ham%usepaw==0) cwaveprj_idat => cwaveprj
1151 142256 : if (fock%use_ACE==0) then
1152 : #if defined HAVE_OPENMP_OFFLOAD
1153 : !$OMP TARGET UPDATE FROM(cwavef,gvnlxc_) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
1154 : #endif
1155 0 : call timab(360,1,tsec)
1156 0 : call fock_getghc(cwavef,cwaveprj,gvnlxc_,gs_ham,mpi_enreg,ndat)
1157 0 : call timab(360,2,tsec)
1158 : #if defined HAVE_OPENMP_OFFLOAD
1159 : !$OMP TARGET UPDATE TO(cwavef,gvnlxc_) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
1160 : #endif
1161 : else
1162 142256 : call fock_ACE_getghc(cwavef,gvnlxc_,gs_ham,mpi_enreg,ndat)
1163 : end if
1164 : end if
1165 : end if
1166 :
1167 0 : else if (type_calc == 3) then
1168 : ! for kinetic and local only, nonlocal and vfock should be zero
1169 0 : if(gs_ham%gpu_option==ABI_GPU_OPENMP) then
1170 0 : call gpu_set_to_zero(gvnlxc_, int(2,c_size_t)*npw_k2*my_nspinor*ndat)
1171 : else
1172 0 : gvnlxc_(:,:) = zero
1173 : end if
1174 : end if ! if(type_calc...
1175 :
1176 : ABI_NVTX_END_RANGE()
1177 :
1178 : !============================================================
1179 : ! Assemble kinetic, local, nonlocal and Fock contributions
1180 : !============================================================
1181 :
1182 : ABI_NVTX_START_RANGE(NVTX_GETGHC_KIN)
1183 :
1184 : #ifdef FC_NVHPC
1185 : !FIXME This Kokkos kernel seems to cause issues under NVHPC so it is disabled
1186 : if (.false.) then
1187 : #else
1188 34757726 : if (gs_ham%gpu_option == ABI_GPU_KOKKOS) then
1189 : #endif
1190 :
1191 : #if defined(HAVE_GPU_CUDA) && defined(HAVE_KOKKOS)
1192 : call assemble_energy_contribution_kokkos(c_loc(ghc), &
1193 : & c_loc(gsc), c_loc(kinpw_k2), c_loc(cwavef), c_loc(gvnlxc_), &
1194 : & ndat, my_nspinor, npw_k2, sij_opt, k1_eq_k2, hugevalue)
1195 : ! sync device so that data can be reused safely on host
1196 : ! will probably be moved elsewhere once all the scf loop runs on device
1197 : call gpu_device_synchronize()
1198 : #endif
1199 :
1200 : else
1201 :
1202 : #ifdef FC_NVHPC
1203 : #if defined(HAVE_GPU_CUDA) && defined(HAVE_KOKKOS)
1204 : !Related to FIXME above
1205 : if (gs_ham%gpu_option == ABI_GPU_KOKKOS) call gpu_device_synchronize()
1206 : #endif
1207 : #endif
1208 :
1209 : ! Assemble modified kinetic, local and nonlocal contributions
1210 : ! to <G|H|C(n,k)>. Take also into account built-in debugging.
1211 34757726 : if(prtvol/=-level)then
1212 :
1213 34757726 : if (gs_ham%gpu_option == ABI_GPU_OPENMP) then
1214 : ! OpenMP GPU
1215 : #ifdef HAVE_OPENMP_OFFLOAD
1216 : if (k1_eq_k2) then
1217 :
1218 : !MG 20260102: With nvfortran 23.11-0, this kernel is a bottleneck due to the filter on kinpw_k2 and the update of ghc.
1219 : ! Solution: branch-free mask + manual loop unrolling. loop unrolling is crucial.
1220 : ! The version with COLLAPSE(3) is faster.
1221 :
1222 : ! !$OMP TARGET TEAMS DISTRIBUTE COLLAPSE(2) MAP(to:ghc,kinpw_k2,gvnlxc_,gsc,cwavef)
1223 : ! !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) PRIVATE(igspinor, kscale) MAP(to:ghc,kinpw_k2,gvnlxc_,gsc,cwavef)
1224 : !$OMP TARGET TEAMS DISTRIBUTE COLLAPSE(2) MAP(to:ghc,kinpw_k2,gvnlxc_,cwavef)
1225 : do idat=1,ndat
1226 : do ispinor=1,my_nspinor
1227 : ! !$OMP PARALLEL DO PRIVATE(igspinor, kscale)
1228 : !$OMP PARALLEL DO PRIVATE(igspinor)
1229 : do ig=1,npw_k2
1230 : igspinor=ig+npw_k2*(ispinor-1)+npw_k2*my_nspinor*(idat-1)
1231 :
1232 : ! ! New version with branch-free mask + manual loop unrolling.
1233 : ! kscale = merge(one, zero, kinpw_k2(ig) < hugevalue)
1234 :
1235 : ! ghc(1,igspinor) = kscale * (ghc(1,igspinor) + kinpw_k2(ig)*cwavef(1,igspinor) + gvnlxc_(1,igspinor))
1236 : ! ghc(2,igspinor) = kscale * (ghc(2,igspinor) + kinpw_k2(ig)*cwavef(2,igspinor) + gvnlxc_(2,igspinor))
1237 : ! if (sij_opt == 1) then
1238 : ! gsc(1,igspinor) = kscale * gsc(1,igspinor)
1239 : ! gsc(2,igspinor) = kscale * gsc(2,igspinor)
1240 : ! end if
1241 : if(kinpw_k2(ig)<huge(zero)*1.d-11)then
1242 : ghc(1,igspinor) = ghc(1,igspinor) + kinpw_k2(ig)*cwavef(1,igspinor) + gvnlxc_(1,igspinor)
1243 : ghc(2,igspinor) = ghc(2,igspinor) + kinpw_k2(ig)*cwavef(2,igspinor) + gvnlxc_(2,igspinor)
1244 : else
1245 : ghc(1,igspinor)=zero
1246 : ghc(2,igspinor)=zero
1247 : end if
1248 : end do ! ig
1249 : end do ! ispinor
1250 : end do ! idat
1251 : if(sij_opt==1) then
1252 : !$OMP TARGET TEAMS DISTRIBUTE COLLAPSE(2) MAP(to:gsc,kinpw_k2)
1253 : do idat=1,ndat
1254 : do ispinor=1,my_nspinor
1255 : !$OMP PARALLEL DO PRIVATE(igspinor)
1256 : do ig=1,npw_k2
1257 : igspinor=ig+npw_k2*(ispinor-1)+npw_k2*my_nspinor*(idat-1)
1258 : if(kinpw_k2(ig)>=huge(zero)*1.d-11)then
1259 : gsc(1,igspinor) = zero
1260 : gsc(2,igspinor) = zero
1261 : end if
1262 : end do ! ig
1263 : end do ! ispinor
1264 : end do ! idat
1265 : end if
1266 : else
1267 : !$OMP TARGET TEAMS DISTRIBUTE COLLAPSE(2) MAP(to:ghc,gvnlxc_,kinpw_k2)
1268 : do idat=1,ndat
1269 : do ispinor=1,my_nspinor
1270 : !$OMP PARALLEL DO PRIVATE(igspinor)
1271 : do ig=1,npw_k2
1272 : igspinor=ig+npw_k2*(ispinor-1)+npw_k2*my_nspinor*(idat-1)
1273 : if(kinpw_k2(ig)<hugevalue)then
1274 : ghc(1,igspinor)= ghc(1,igspinor) + gvnlxc_(1,igspinor)
1275 : ghc(2,igspinor)= ghc(2,igspinor) + gvnlxc_(2,igspinor)
1276 : else
1277 : ghc(1,igspinor)=zero
1278 : ghc(2,igspinor)=zero
1279 : end if
1280 : end do ! ig
1281 : end do ! ispinor
1282 : end do ! idat
1283 : if(sij_opt==1) then
1284 : !$OMP TARGET TEAMS DISTRIBUTE COLLAPSE(2) MAP(to:gsc,kinpw_k2)
1285 : do idat=1,ndat
1286 : do ispinor=1,my_nspinor
1287 : !$OMP PARALLEL DO PRIVATE(igspinor)
1288 : do ig=1,npw_k2
1289 : igspinor=ig+npw_k2*(ispinor-1)+npw_k2*my_nspinor*(idat-1)
1290 : if(kinpw_k2(ig)>=huge(zero)*1.d-11)then
1291 : gsc(1,igspinor)=zero
1292 : gsc(2,igspinor)=zero
1293 : end if
1294 : end do ! ig
1295 : end do ! ispinor
1296 : end do ! idat
1297 : end if
1298 : end if
1299 : #endif
1300 :
1301 : else
1302 :
1303 : !CPU (+ Kokkos eventually)
1304 34757726 : if (k1_eq_k2) then
1305 : !$OMP PARALLEL DO PRIVATE(igspinor) COLLAPSE(2) IF(gemm_nonlop_use_gemm)
1306 70691914 : do idat=1,ndat
1307 109182754 : do ispinor=1,my_nspinor
1308 10812790917 : do ig=1,npw_k2
1309 10738226770 : igspinor=ig+npw_k2*(ispinor-1)+npw_k2*my_nspinor*(idat-1)
1310 10776717610 : if(kinpw_k2(ig)<hugevalue)then
1311 53193739480 : ghc(:,igspinor) = ghc(:,igspinor) + kinpw_k2(ig)*cwavef(:,igspinor) + gvnlxc_(:,igspinor)
1312 : else
1313 298436622 : ghc(:,igspinor)=zero
1314 142274576 : if (sij_opt==1) gsc(:,igspinor)=zero
1315 : end if
1316 : end do ! ig
1317 : end do ! ispinor
1318 : end do ! idat
1319 : else
1320 139119 : if (gs_ham%use_gbt == 0) then
1321 : !$OMP PARALLEL DO PRIVATE(igspinor) COLLAPSE(2) IF(gemm_nonlop_use_gemm)
1322 0 : do idat=1,ndat
1323 0 : do ispinor=1,my_nspinor
1324 0 : do ig=1,npw_k2
1325 0 : igspinor=ig+npw_k2*(ispinor-1)+npw_k2*my_nspinor*(idat-1)
1326 0 : if(kinpw_k2(ig)<hugevalue)then
1327 0 : ghc(:,igspinor)= ghc(:,igspinor) + gvnlxc_(:,igspinor)
1328 : else
1329 0 : ghc(:,igspinor)=zero
1330 0 : if (sij_opt==1) gsc(:,igspinor)=zero
1331 : end if
1332 : end do ! ig
1333 : end do ! ispinor
1334 : end do ! idat
1335 : else
1336 : ! GBT. use different kinetic energies for up and down components.
1337 : !$OMP PARALLEL DO PRIVATE(igspinor, iispinor) COLLAPSE(2) IF(gemm_nonlop_use_gemm)
1338 278238 : do idat=1,ndat
1339 556476 : do ispinor=1,my_nspinor
1340 278238 : iispinor=ispinor; if (mpi_enreg%paral_spinor==1) iispinor=mpi_enreg%me_spinor+1
1341 417357 : if (iispinor == 1) then
1342 31864613 : do ig=1,npw_k2
1343 31725494 : igspinor=ig+npw_k2*(ispinor-1)+npw_k2*my_nspinor*(idat-1)
1344 31864613 : if(gs_ham%kinpw_k(ig)<hugevalue)then
1345 153976375 : ghc(:,igspinor) = ghc(:,igspinor) + gs_ham%kinpw_k(ig)*cwavef(:,igspinor) + gvnlxc_(:,igspinor)
1346 : else
1347 2790657 : ghc(:,igspinor)=zero
1348 930219 : if (sij_opt==1) gsc(:,igspinor)=zero
1349 : end if
1350 : end do ! ig
1351 : else
1352 31864613 : do ig=1,npw_k2
1353 31725494 : igspinor=ig+npw_k2*(ispinor-1)+npw_k2*my_nspinor*(idat-1)
1354 31864613 : if(gs_ham%kinpw_kp(ig)<hugevalue)then
1355 153976375 : ghc(:,igspinor) = ghc(:,igspinor) + gs_ham%kinpw_kp(ig)*cwavef(:,igspinor) + gvnlxc_(:,igspinor)
1356 : else
1357 2790657 : ghc(:,igspinor)=zero
1358 930219 : if (sij_opt==1) gsc(:,igspinor)=zero
1359 : end if
1360 : end do ! ig
1361 : end if
1362 : end do ! ispinor
1363 : end do ! idat
1364 : end if
1365 : end if
1366 :
1367 : end if ! gs_ham%gpu_option
1368 :
1369 : else
1370 : ! Here, debugging section
1371 : #ifdef HAVE_OPENMP_OFFLOAD
1372 : !$OMP TARGET UPDATE FROM(ghc,gsc,cwavef,gvnlxc_) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
1373 : #endif
1374 0 : call wrtout(std_out,' getghc : components of ghc ','PERS')
1375 : write(msg,'(a)')&
1376 0 : 'icp ig ispinor igspinor re/im ghc kinpw cwavef glocc gvnlxc gsc'
1377 0 : call wrtout(std_out,msg,'PERS')
1378 0 : do idat=1,ndat
1379 0 : do ispinor=1,my_nspinor
1380 0 : do ig=1,npw_k2
1381 0 : igspinor=ig+npw_k2*(ispinor-1)+npw_k2*my_nspinor*(idat-1)
1382 0 : if(kinpw_k2(ig)<hugevalue)then
1383 0 : if (k1_eq_k2) then
1384 0 : ghcre=kinpw_k2(ig)*cwavef(1,igspinor)+ghc(1,igspinor)+gvnlxc_(1,igspinor)
1385 0 : ghcim=kinpw_k2(ig)*cwavef(2,igspinor)+ghc(2,igspinor)+gvnlxc_(2,igspinor)
1386 : else
1387 0 : ghcre=ghc(1,igspinor)+gvnlxc_(1,igspinor)
1388 0 : ghcim=ghc(2,igspinor)+gvnlxc_(2,igspinor)
1389 : end if
1390 : else
1391 0 : ghcre=zero
1392 0 : ghcim=zero
1393 0 : if (sij_opt==1) gsc(:,igspinor)=zero
1394 : end if
1395 0 : iispinor=ispinor; if (mpi_enreg%paral_spinor==1) iispinor=mpi_enreg%me_spinor+1
1396 0 : if (sij_opt == 1) then
1397 0 : write(msg,'(a,3(1x,i5),6(1x,es13.6))') ' 1 ', ig, iispinor, igspinor,ghcre,&
1398 0 : kinpw_k2(ig),cwavef(1,igspinor),ghc(1,igspinor),gvnlxc_(1,igspinor), gsc(1,igspinor)
1399 0 : call wrtout(std_out,msg,'PERS')
1400 0 : write(msg,'(a,3(1x,i5),6(1x,es13.6))') ' 2 ', ig, iispinor, igspinor,ghcim,&
1401 0 : kinpw_k2(ig),cwavef(2,igspinor),ghc(2,igspinor),gvnlxc_(2,igspinor), gsc(2,igspinor)
1402 0 : call wrtout(std_out,msg,'PERS')
1403 : else
1404 0 : write(msg,'(a,3(1x,i5),6(1x,es13.6))') ' 1 ', ig, iispinor, igspinor,ghcre,&
1405 0 : kinpw_k2(ig),cwavef(1,igspinor),ghc(1,igspinor),gvnlxc_(1,igspinor)
1406 0 : call wrtout(std_out,msg,'PERS')
1407 0 : write(msg,'(a,3(1x,i5),6(1x,es13.6))') ' 2 ', ig, iispinor, igspinor,ghcim,&
1408 0 : kinpw_k2(ig),cwavef(2,igspinor),ghc(2,igspinor),gvnlxc_(2,igspinor)
1409 0 : call wrtout(std_out,msg,'PERS')
1410 : end if
1411 0 : ghc(:,igspinor) = [ghcre, ghcim]
1412 : end do ! ig
1413 : end do ! ispinor
1414 : end do ! idat
1415 : #ifdef HAVE_OPENMP_OFFLOAD
1416 : !$OMP TARGET UPDATE TO(ghc,gsc) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
1417 : #endif
1418 : end if
1419 : end if ! gs_ham%gpu_option
1420 :
1421 : ABI_NVTX_END_RANGE()
1422 :
1423 : ! Special case of PAW + Fock : only return Fock operator contribution in gvnlxc_
1424 34757726 : if (gs_ham%usepaw==1 .and. has_fock) then
1425 13114 : if(gs_ham%gpu_option == ABI_GPU_OPENMP) then
1426 : #ifdef HAVE_OPENMP_OFFLOAD
1427 : call abi_xaxpy(2*npw_k2*my_nspinor*ndat, cminusone, gvnlc, 1, gvnlxc_, 1, x_cplx=1, gpu_option=gs_ham%gpu_option)
1428 : !$OMP TARGET EXIT DATA MAP(delete:gvnlc) IF(gs_ham%gpu_option == ABI_GPU_OPENMP)
1429 : #endif
1430 : else
1431 48872050 : gvnlxc_=gvnlxc_-gvnlc
1432 : end if
1433 13114 : if(gs_ham%gpu_option==ABI_GPU_KOKKOS) then
1434 : #if defined HAVE_GPU && defined HAVE_YAKL
1435 : ABI_FREE_MANAGED(gvnlc)
1436 : #endif
1437 : else
1438 13114 : ABI_FREE(gvnlc)
1439 : end if
1440 : endif
1441 :
1442 : #ifdef HAVE_OPENMP_OFFLOAD
1443 : !$OMP TARGET UPDATE FROM(ghc) IF(transfer_ghc)
1444 : !$OMP TARGET UPDATE FROM(gsc) IF(transfer_gsc)
1445 : !$OMP TARGET UPDATE FROM(cwavef) IF(transfer_cwavef)
1446 : !$OMP TARGET UPDATE FROM(gvnlxc_) IF(transfer_gvnlxc .and. .not. local_gvnlxc)
1447 : !$OMP TARGET EXIT DATA MAP(delete:gvnlxc_) IF(transfer_gvnlxc)
1448 : #endif
1449 34757726 : if (local_gvnlxc) then
1450 880108 : if(gs_ham%gpu_option==ABI_GPU_KOKKOS) then
1451 : #if defined HAVE_GPU && defined HAVE_YAKL
1452 : ABI_FREE_MANAGED(gvnlxc_)
1453 : #endif
1454 : else
1455 880108 : ABI_FREE(gvnlxc_)
1456 : end if
1457 : end if
1458 :
1459 : ! Structured debugging: if prtvol=-level, stop here.
1460 34757726 : if (prtvol == -level) then
1461 0 : ABI_ERROR(sjoin(' getghc: exit prtvol=-',itoa(level),', debugging mode => stop '))
1462 : end if
1463 :
1464 34757726 : if (type_calc==0.or.type_calc==2) then
1465 34757726 : if (has_fock.and.gs_ham%usepaw==1.and.cpopt<2) then
1466 13114 : call pawcprj_free(cwaveprj_fock)
1467 13114 : ABI_FREE(cwaveprj_fock)
1468 : end if
1469 : end if
1470 :
1471 : end if ! type_calc
1472 :
1473 : #ifdef HAVE_OPENMP_OFFLOAD
1474 : !$OMP TARGET EXIT DATA MAP(delete:ghc) IF(transfer_ghc)
1475 : !$OMP TARGET EXIT DATA MAP(delete:gsc) IF(transfer_gsc)
1476 : !$OMP TARGET EXIT DATA MAP(delete:cwavef) IF(transfer_cwavef)
1477 : #endif
1478 34965650 : call timab(350+tim_getghc,2,tsec)
1479 :
1480 : DBG_EXIT("COLL")
1481 : ABI_NVTX_END_RANGE()
1482 :
1483 69931300 : end subroutine getghc
1484 : !!***
1485 :
1486 : !----------------------------------------------------------------------
1487 :
1488 : !!****f* ABINIT/getghc_nucdip
1489 : !!
1490 : !! NAME
1491 : !! getghc_nucdip
1492 : !!
1493 : !! FUNCTION
1494 : !! Compute magnetic nuclear dipole moment contribution to <G|H|C>
1495 : !! for input vector |C> expressed in reciprocal space.
1496 : !!
1497 : !! INPUTS
1498 : !! cwavef(2,npw_k*my_nspinor*ndat)=planewave coefficients of wavefunction.
1499 : !! gbound_k(2*mgfft+4)=sphere boundary info
1500 : !! gprimd(3,3)=dimensional reciprocal space primitive translations (b^-1)
1501 : !! istwf_k=input parameter that describes the storage of wfs
1502 : !! kg_k(3,npw_k)=G vec coordinates wrt recip lattice transl.
1503 : !! kpt(3)=current k point
1504 : !! mgfft=maximum single fft dimension
1505 : !! mpi_enreg=information about MPI parallelization
1506 : !! my_nspinor=number of spinorial components of the wavefunctions (on current proc)
1507 : !! ndat=number of FFTs to perform in parall
1508 : !! ngfft(18)=contain all needed information about 3D FFT
1509 : !! npw_k=number of planewaves in basis for given k point.
1510 : !! nvloc=number of spin components of vxctaulocal
1511 : !! n4,n5,n6=for dimensioning of vxctaulocal
1512 : !! gpu_option= GPU implementation to use, i.e. cuda, openMP, ... (0=not using GPU)
1513 : !! vectornd(n4,n5,n6,nvloc,3)= local potential corresponding to the vector potential of the array
1514 : !! of nuclear magnetic dipoles, in real space, on the augmented fft grid.
1515 : !!
1516 : !! OUTPUT
1517 : !! ghc_vectornd(2,npw_k*my_nspinor*ndat)=A.p contribution to <G|H|C> for array of nuclear dipoles
1518 : !!
1519 : !! SIDE EFFECTS
1520 : !!
1521 : !! NOTES
1522 : !! this code is a copied, simplified version of getghc_mGGA (see below) and should eventually be
1523 : !! integrated into that code, to simplify maintenance
1524 : !!
1525 : !! SOURCE
1526 :
1527 812570 : subroutine getghc_nucdip(cwavef,ghc_vectornd,gbound_k,istwf_k,kg_k,kpt,mgfft,mpi_enreg,&
1528 812570 : & ndat,ngfft,npw_k,nvloc,n4,n5,n6,my_nspinor,vectornd,vlocal,zora,gpu_option)
1529 :
1530 : !Arguments ------------------------------------
1531 : !scalars
1532 : integer,intent(in) :: istwf_k,mgfft,my_nspinor,ndat,npw_k,nvloc,n4,n5,n6,gpu_option,zora
1533 : type(MPI_type),intent(in) :: mpi_enreg
1534 : !arrays
1535 : integer,intent(in) :: gbound_k(2*mgfft+4),kg_k(3,npw_k),ngfft(18)
1536 : real(dp),intent(in) :: kpt(3)
1537 : real(dp),intent(inout) :: cwavef(2,npw_k*my_nspinor*ndat)
1538 : real(dp),intent(inout) :: ghc_vectornd(2,npw_k*my_nspinor*ndat)
1539 : real(dp),intent(inout) :: vectornd(n4,n5,n6,nvloc,3),vlocal(n4,n5,n6,nvloc)
1540 :
1541 : !Local variables-------------------------------
1542 : !scalars
1543 : integer,parameter :: tim_fourwf=1
1544 : integer :: idat,idir,ipw,iv1,iv2,nspinortot,shift
1545 : logical :: nspinor1TreatedByThisProc,nspinor2TreatedByThisProc,usezora
1546 : real(dp), parameter :: HalfFineStruct2=half/InvFineStruct**2
1547 : real(dp) :: weight=one
1548 : !arrays
1549 812570 : real(dp),allocatable :: cwavef1(:,:),cwavef2(:,:)
1550 812570 : real(dp),allocatable :: gcwavef(:,:,:),gcwavef1(:,:,:),gcwavef2(:,:,:)
1551 812570 : real(dp),allocatable :: ghc1(:,:),ghc2(:,:),kgkpk(:,:),vectornd_dir(:,:,:,:)
1552 812570 : real(dp),allocatable :: work(:,:,:,:),zk(:,:,:,:)
1553 : ! *********************************************************************
1554 :
1555 1127843222 : ghc_vectornd(:,:)=zero
1556 :
1557 : !! JWZ debug initial code was only for nvloc==1 case
1558 812570 : if (nvloc/=1) return
1559 :
1560 812570 : nspinortot=min(2,(1+mpi_enreg%paral_spinor)*my_nspinor)
1561 812570 : if (mpi_enreg%paral_spinor==0) then
1562 812570 : shift=npw_k
1563 812570 : nspinor1TreatedByThisProc=.true.
1564 812570 : nspinor2TreatedByThisProc=(nspinortot==2)
1565 : else
1566 0 : shift=0
1567 0 : nspinor1TreatedByThisProc=(mpi_enreg%me_spinor==0)
1568 0 : nspinor2TreatedByThisProc=(mpi_enreg%me_spinor==1)
1569 : end if
1570 :
1571 812570 : usezora=((zora.EQ.1).OR.(zora.EQ.3))
1572 812570 : if(usezora) then
1573 0 : ABI_MALLOC(zk,(n4,n5,n6,nvloc))
1574 0 : zk(1:n4,1:1:n5,1:n6,1:nvloc)=1.0/(1.0-HalfFineStruct2*vlocal(1:n4,1:n5,1:n6,1:nvloc))
1575 : end if
1576 :
1577 4062850 : ABI_MALLOC(work,(2,n4,n5,n6*ndat))
1578 :
1579 812570 : if (nspinortot==1) then
1580 :
1581 1754592 : ABI_MALLOC(ghc1,(2,npw_k*ndat))
1582 :
1583 : ! Do it in 2 STEPs:
1584 : ! STEP1: Compute grad of cwavef
1585 2339456 : ABI_MALLOC(gcwavef,(2,npw_k*ndat,3))
1586 :
1587 1057250534 : gcwavef = zero
1588 :
1589 : ! compute k + G. Note these are in reduced coords
1590 1754592 : ABI_MALLOC(kgkpk,(npw_k,3))
1591 117797206 : do ipw = 1, npw_k
1592 469434232 : kgkpk(ipw,:) = kpt(:) + kg_k(:,ipw)
1593 : end do
1594 :
1595 : ! make 2\pi(k+G)c(G)|G> by element-wise multiplication
1596 2339456 : do idir = 1, 3
1597 4094048 : do idat = 1, ndat
1598 355146210 : do ipw=1,npw_k
1599 351637026 : gcwavef(1,ipw+(idat-1)*npw_k,idir) = cwavef(1,ipw+(idat-1)*npw_k)*kgkpk(ipw,idir)
1600 353391618 : gcwavef(2,ipw+(idat-1)*npw_k,idir) = cwavef(2,ipw+(idat-1)*npw_k)*kgkpk(ipw,idir)
1601 : end do
1602 : end do
1603 : end do
1604 584864 : ABI_FREE(kgkpk)
1605 1057250534 : gcwavef = gcwavef*two_pi
1606 :
1607 : ! STEP2: Compute sum of (grad components of vectornd)*(grad components of cwavef)
1608 3509184 : ABI_MALLOC(vectornd_dir,(n4,n5,n6,nvloc))
1609 2339456 : do idir=1,3
1610 1754592 : if (usezora) then
1611 0 : vectornd_dir(1:n4,1:n5,1:n6,1:nvloc)=zk(1:n4,1:n5,1:n6,1:nvloc)*vectornd(1:n4,1:n5,1:n6,1:nvloc,idir)
1612 : else
1613 10314799284 : vectornd_dir(1:n4,1:n5,1:n6,1:nvloc)=vectornd(1:n4,1:n5,1:n6,1:nvloc,idir)
1614 : end if
1615 : call fourwf(1,vectornd_dir,gcwavef(:,:,idir),ghc1,work,gbound_k,gbound_k,&
1616 : istwf_k,kg_k,kg_k,mgfft,mpi_enreg,ndat,ngfft,npw_k,npw_k,n4,n5,n6,2,&
1617 1754592 : & tim_fourwf,weight,weight,gpu_option=gpu_option)
1618 : !!$OMP PARALLEL DO
1619 4094048 : do idat=1,ndat
1620 355146210 : do ipw=1,npw_k
1621 1056665670 : ghc_vectornd(:,ipw+(idat-1)*npw_k)=ghc_vectornd(:,ipw+(idat-1)*npw_k)+ghc1(:,ipw+(idat-1)*npw_k)
1622 : end do
1623 : end do
1624 : !ghc_vectornd=ghc_vectornd+ghc1
1625 : end do ! idir
1626 584864 : ABI_FREE(vectornd_dir)
1627 584864 : ABI_FREE(gcwavef)
1628 584864 : ABI_FREE(ghc1)
1629 :
1630 : else ! nspinortot==2
1631 :
1632 683118 : ABI_MALLOC(cwavef1,(2,npw_k*ndat))
1633 455412 : ABI_MALLOC(cwavef2,(2,npw_k*ndat))
1634 455412 : do idat=1,ndat
1635 227706 : iv1=1+(idat-1)*npw_k; iv2=-1+iv1+npw_k
1636 387924519 : cwavef1(1:2,iv1:iv2) = cwavef(1:2,1+(idat-1)*my_nspinor*npw_k:npw_k+(idat-1)*my_nspinor*npw_k)
1637 : cwavef2(1:2,iv1:iv2) = &
1638 388152225 : & cwavef(1:2,1+(idat-1)*my_nspinor*npw_k+shift:npw_k+(idat-1)*my_nspinor*npw_k+shift)
1639 : end do
1640 :
1641 : ! compute k + G. Note these are in reduced coords
1642 683118 : ABI_MALLOC(kgkpk,(npw_k,3))
1643 129459977 : do ipw = 1, npw_k
1644 517156790 : kgkpk(ipw,:) = kpt(:) + kg_k(:,ipw)
1645 : end do
1646 :
1647 227706 : if (nspinor1TreatedByThisProc) then
1648 :
1649 455412 : ABI_MALLOC(ghc1,(2,npw_k*ndat))
1650 :
1651 : ! Do it in 2 STEPs:
1652 : ! STEP1: Compute grad of cwavef
1653 910824 : ABI_MALLOC(gcwavef1,(2,npw_k*ndat,3))
1654 :
1655 1164001263 : gcwavef1 = zero
1656 : ! make 2\pi(k+G)c(G)|G> by element-wise multiplication
1657 910824 : do idir = 1, 3
1658 1593942 : do idat = 1, ndat
1659 683118 : iv1=1+(idat-1)*npw_k; iv2=-1+iv1+npw_k
1660 388379931 : gcwavef1(1,iv1:iv2,idir) = cwavef1(1,iv1:iv2)*kgkpk(1:npw_k,idir)
1661 389063049 : gcwavef1(2,iv1:iv2,idir) = cwavef1(2,iv1:iv2)*kgkpk(1:npw_k,idir)
1662 : end do
1663 : end do
1664 1164001263 : gcwavef1 = gcwavef1*two_pi
1665 :
1666 : ! STEP2: Compute sum of (grad components of vectornd)*(grad components of cwavef)
1667 1366236 : ABI_MALLOC(vectornd_dir,(n4,n5,n6,nvloc))
1668 910824 : do idir=1,3
1669 683118 : if (usezora) then
1670 0 : vectornd_dir(1:n4,1:n5,1:n6,1:nvloc)=zk(1:n4,1:n5,1:n6,1:nvloc)*vectornd(1:n4,1:n5,1:n6,1:nvloc,idir)
1671 : else
1672 8256805533 : vectornd_dir(1:n4,1:n5,1:n6,1:nvloc)=vectornd(1:n4,1:n5,1:n6,1:nvloc,idir)
1673 : end if
1674 : call fourwf(1,vectornd_dir,gcwavef1(:,:,idir),ghc1,work,gbound_k,gbound_k,&
1675 : & istwf_k,kg_k,kg_k,mgfft,mpi_enreg,ndat,ngfft,npw_k,npw_k,n4,n5,n6,2,&
1676 683118 : & tim_fourwf,weight,weight,gpu_option=gpu_option)
1677 : !!$OMP PARALLEL DO
1678 1593942 : do idat=1,ndat
1679 683118 : iv1=1+(idat-1)*npw_k; iv2=-1+iv1+npw_k
1680 : ghc_vectornd(1:2,iv1:iv2)=ghc_vectornd(1:2,iv1:iv2)+&
1681 1164456675 : & ghc1(1:2,iv1:iv2)
1682 : end do
1683 : end do ! idir
1684 227706 : ABI_FREE(vectornd_dir)
1685 227706 : ABI_FREE(gcwavef1)
1686 227706 : ABI_FREE(ghc1)
1687 :
1688 : end if ! end spinor 1
1689 :
1690 227706 : if (nspinor2TreatedByThisProc) then
1691 :
1692 455412 : ABI_MALLOC(ghc2,(2,npw_k*ndat))
1693 :
1694 : ! Do it in 2 STEPs:
1695 : ! STEP1: Compute grad of cwavef
1696 910824 : ABI_MALLOC(gcwavef2,(2,npw_k*ndat,3))
1697 1164001263 : gcwavef2 = zero
1698 : ! make 2\pi(k+G)c(G)|G> by element-wise multiplication
1699 910824 : do idir = 1, 3
1700 1593942 : do idat = 1, ndat
1701 683118 : iv1=1+(idat-1)*npw_k; iv2=-1+iv1+npw_k
1702 388379931 : gcwavef2(1,iv1:iv2,idir) = cwavef2(1,iv1:iv2)*kgkpk(1:npw_k,idir)
1703 389063049 : gcwavef2(2,iv1:iv2,idir) = cwavef2(2,iv1:iv2)*kgkpk(1:npw_k,idir)
1704 : end do
1705 : end do
1706 1164001263 : gcwavef2 = gcwavef2*two_pi
1707 :
1708 : ! STEP2: Compute sum of (grad components of vectornd)*(grad components of cwavef)
1709 1366236 : ABI_MALLOC(vectornd_dir,(n4,n5,n6,nvloc))
1710 910824 : do idir=1,3
1711 683118 : if (usezora) then
1712 0 : vectornd_dir(1:n4,1:n5,1:n6,1:nvloc)=zk(1:n4,1:n5,1:n6,1:nvloc)*vectornd(1:n4,1:n5,1:n6,1:nvloc,idir)
1713 : else
1714 8256805533 : vectornd_dir(1:n4,1:n5,1:n6,1:nvloc)=vectornd(1:n4,1:n5,1:n6,1:nvloc,idir)
1715 : end if
1716 : call fourwf(1,vectornd_dir,gcwavef2(:,:,idir),ghc2,work,gbound_k,gbound_k,&
1717 : & istwf_k,kg_k,kg_k,mgfft,mpi_enreg,ndat,ngfft,npw_k,npw_k,n4,n5,n6,2,&
1718 683118 : & tim_fourwf,weight,weight,gpu_option=gpu_option)
1719 : !!$OMP PARALLEL DO
1720 1593942 : do idat=1,ndat
1721 683118 : iv1=1+(idat-1)*npw_k; iv2=-1+iv1+npw_k
1722 : ghc_vectornd(1:2,iv1+shift:iv2+shift)=ghc_vectornd(1:2,iv1+shift:iv2+shift)+&
1723 1164456675 : & ghc2(1:2,iv1:iv2)
1724 : end do
1725 : end do ! idir
1726 227706 : ABI_FREE(vectornd_dir)
1727 227706 : ABI_FREE(gcwavef2)
1728 227706 : ABI_FREE(ghc2)
1729 :
1730 : end if ! end spinor 2
1731 :
1732 227706 : ABI_FREE(cwavef1)
1733 227706 : ABI_FREE(cwavef2)
1734 227706 : ABI_FREE(kgkpk)
1735 :
1736 : end if ! nspinortot
1737 :
1738 812570 : ABI_FREE(work)
1739 812570 : if(usezora) then
1740 0 : ABI_FREE(zk)
1741 : end if
1742 :
1743 812570 : end subroutine getghc_nucdip
1744 : !!***
1745 :
1746 : !!****f* ABINIT/getghc_mGGA
1747 : !!
1748 : !! NAME
1749 : !! getghc_mGGA
1750 : !!
1751 : !! FUNCTION
1752 : !! Compute metaGGA contribution to <G|H|C> for input vector |C> expressed in reciprocal space.
1753 : !!
1754 : !! INPUTS
1755 : !! cwavef(2,npw_k*my_nspinor*ndat)=planewave coefficients of wavefunction.
1756 : !! gbound_k(2*mgfft+4)=sphere boundary info
1757 : !! gprimd(3,3)=dimensional reciprocal space primitive translations (b^-1)
1758 : !! istwf_k=input parameter that describes the storage of wfs
1759 : !! kg_k(3,npw_k)=G vec coordinates wrt recip lattice transl.
1760 : !! kpt(3)=current k point
1761 : !! mgfft=maximum single fft dimension
1762 : !! mpi_enreg=information about MPI parallelization
1763 : !! my_nspinor=number of spinorial components of the wavefunctions (on current proc)
1764 : !! ndat=number of FFTs to perform in parall
1765 : !! ngfft(18)=contain all needed information about 3D FFT
1766 : !! npw_k=number of planewaves in basis for given k point.
1767 : !! nvloc=number of spin components of vxctaulocal
1768 : !! n4,n5,n6=for dimensionning of vxctaulocal
1769 : !! gpu_option= GPU implementation to use, i.e. cuda, openMP, ... (0=not using GPU)
1770 : !! vxctaulocal(n4,n5,n6,nvloc,4)= local potential corresponding to the derivative of XC energy with respect to
1771 : !! kinetic energy density, in real space, on the augmented fft grid.
1772 : !! This array contains also the gradient of vxctaulocal (gvxctaulocal) in vxctaulocal(:,:,:,:,2:4).
1773 : !!
1774 : !! OUTPUT
1775 : !! ghc_mGGA(2,npw_k*my_nspinor*ndat)=metaGGA contribution to <G|H|C>
1776 : !!
1777 : !! SIDE EFFECTS
1778 : !!
1779 : !! SOURCE
1780 :
1781 98528 : subroutine getghc_mGGA(cwavef,ghc_mGGA,gbound_k,gprimd,istwf_k,kg_k,kpt,mgfft,mpi_enreg,&
1782 98528 : & ndat,ngfft,npw_k,nvloc,n4,n5,n6,my_nspinor,vxctaulocal,gpu_option)
1783 :
1784 : !Arguments ------------------------------------
1785 : !scalars
1786 : integer,intent(in) :: istwf_k,mgfft,my_nspinor,ndat,npw_k,nvloc,n4,n5,n6,gpu_option
1787 : type(MPI_type),intent(in) :: mpi_enreg
1788 : !arrays
1789 : integer,intent(in) :: gbound_k(2*mgfft+4),kg_k(3,npw_k),ngfft(18)
1790 : real(dp),intent(in) :: gprimd(3,3),kpt(3)
1791 : real(dp),intent(inout) :: cwavef(2,npw_k*my_nspinor*ndat)
1792 : real(dp),intent(inout) :: ghc_mGGA(2,npw_k*my_nspinor*ndat)
1793 : real(dp),intent(inout) :: vxctaulocal(n4,n5,n6,nvloc,4)
1794 :
1795 : !Local variables-------------------------------
1796 : !scalars
1797 : integer,parameter :: tim_fourwf=1
1798 : integer :: idat,idir,ipw,nspinortot,shift
1799 : logical :: nspinor1TreatedByThisProc,nspinor2TreatedByThisProc
1800 : real(dp) :: weight=one
1801 : !arrays
1802 : real(dp) :: kg_k_cart_vec(3)
1803 98528 : real(dp),allocatable :: cwavef1(:,:),cwavef2(:,:)
1804 98528 : real(dp),allocatable :: gcwavef(:,:,:),gcwavef1(:,:,:),gcwavef2(:,:,:)
1805 98528 : real(dp),allocatable :: ghc1(:,:),ghc2(:,:)
1806 98528 : real(dp),allocatable :: lcwavef(:,:),lcwavef1(:,:),lcwavef2(:,:)
1807 98528 : real(dp),allocatable :: work(:,:,:,:)
1808 : ! *********************************************************************
1809 :
1810 176135072 : ghc_mGGA(:,:)=zero
1811 :
1812 98528 : if (nvloc/=1) return
1813 :
1814 98528 : nspinortot=min(2,(1+mpi_enreg%paral_spinor)*my_nspinor)
1815 98528 : if (mpi_enreg%paral_spinor==0) then
1816 98528 : shift=npw_k
1817 98528 : nspinor1TreatedByThisProc=.true.
1818 98528 : nspinor2TreatedByThisProc=(nspinortot==2)
1819 : else
1820 0 : shift=0
1821 0 : nspinor1TreatedByThisProc=(mpi_enreg%me_spinor==0)
1822 0 : nspinor2TreatedByThisProc=(mpi_enreg%me_spinor==1)
1823 : end if
1824 :
1825 492640 : ABI_MALLOC(work,(2,n4,n5,n6*ndat))
1826 :
1827 98528 : if (nspinortot==1) then
1828 :
1829 136392 : ABI_MALLOC(ghc1,(2,npw_k*ndat))
1830 :
1831 : ! Do it in 3 STEPs:
1832 : ! STEP1: Compute grad of cwavef and Laplacian of cwavef
1833 181856 : ABI_MALLOC(gcwavef,(2,npw_k*ndat,3))
1834 90928 : ABI_MALLOC(lcwavef,(2,npw_k*ndat))
1835 : !!$OMP PARALLEL DO
1836 387384872 : gcwavef = zero; lcwavef = zero
1837 95408 : do idat=1,ndat
1838 32362326 : do ipw=1,npw_k
1839 : ! convert k + G from reduced coords to Cartesian
1840 613071442 : kg_k_cart_vec = two_pi*MATMUL(gprimd,kpt(1:3)+kg_k(1:3,ipw))
1841 : ! form \grad\psi = i(k + G) \psi in Cartesian frame
1842 129067672 : gcwavef(1,ipw+(idat-1)*npw_k,1:3)= cwavef(2,ipw+(idat-1)*npw_k)*kg_k_cart_vec(1:3)
1843 129067672 : gcwavef(2,ipw+(idat-1)*npw_k,1:3)= -cwavef(1,ipw+(idat-1)*npw_k)*kg_k_cart_vec(1:3)
1844 : ! form \nabla^2\psi = -|k + G|^2 \psi
1845 : lcwavef(1:2,ipw+(idat-1)*npw_k)=&
1846 193651452 : &lcwavef(1:2,ipw+(idat-1)*npw_k)-cwavef(1:2,ipw+(idat-1)*npw_k)*DOT_PRODUCT(kg_k_cart_vec,kg_k_cart_vec)
1847 : end do
1848 : end do
1849 : ! STEP2: Compute (vxctaulocal)*(Laplacian of cwavef) and add it to ghc
1850 : call fourwf(1,vxctaulocal(:,:,:,:,1),lcwavef,ghc1,work,gbound_k,gbound_k,&
1851 : & istwf_k,kg_k,kg_k,mgfft,mpi_enreg,ndat,ngfft,npw_k,npw_k,n4,n5,n6,2,&
1852 45464 : & tim_fourwf,weight,weight,gpu_option=gpu_option)
1853 : !!$OMP PARALLEL DO
1854 95408 : do idat=1,ndat
1855 32362326 : do ipw=1,npw_k
1856 96850698 : ghc_mGGA(:,ipw+(idat-1)*npw_k)=ghc_mGGA(:,ipw+(idat-1)*npw_k)-half*ghc1(:,ipw+(idat-1)*npw_k)
1857 : end do
1858 : end do
1859 45464 : ABI_FREE(lcwavef)
1860 : ! STEP3: Compute sum of (grad components of vxctaulocal)*(grad components of cwavef)
1861 : ! note: since grad cwavef is in Cart frame, evidently grad vxc is also
1862 181856 : do idir=1,3
1863 : call fourwf(1,vxctaulocal(:,:,:,:,1+idir),gcwavef(:,:,idir),ghc1,work,gbound_k,gbound_k,&
1864 : istwf_k,kg_k,kg_k,mgfft,mpi_enreg,ndat,ngfft,npw_k,npw_k,n4,n5,n6,2,&
1865 136392 : & tim_fourwf,weight,weight,gpu_option=gpu_option)
1866 : !!$OMP PARALLEL DO
1867 331688 : do idat=1,ndat
1868 97086978 : do ipw=1,npw_k
1869 290552094 : ghc_mGGA(:,ipw+(idat-1)*npw_k)=ghc_mGGA(:,ipw+(idat-1)*npw_k)-half*ghc1(:,ipw+(idat-1)*npw_k)
1870 : end do
1871 : end do
1872 : end do ! idir
1873 45464 : ABI_FREE(gcwavef)
1874 45464 : ABI_FREE(ghc1)
1875 :
1876 : else ! nspinortot==2
1877 :
1878 159192 : ABI_MALLOC(cwavef1,(2,npw_k*ndat))
1879 106128 : ABI_MALLOC(cwavef2,(2,npw_k*ndat))
1880 109248 : do idat=1,ndat
1881 13315213 : do ipw=1,npw_k
1882 39617895 : cwavef1(1:2,ipw+(idat-1)*npw_k)=cwavef(1:2,ipw+(idat-1)*my_nspinor*npw_k)
1883 39674079 : cwavef2(1:2,ipw+(idat-1)*npw_k)=cwavef(1:2,ipw+(idat-1)*my_nspinor*npw_k+shift)
1884 : end do
1885 : end do
1886 : ! call cg_zcopy(npw*ndat,cwavef(1,1),cwavef1)
1887 : ! call cg_zcopy(npw*ndat,cwavef(1,1+shift),cwavef2)
1888 :
1889 :
1890 53064 : if (nspinor1TreatedByThisProc) then
1891 :
1892 106128 : ABI_MALLOC(ghc1,(2,npw_k*ndat))
1893 :
1894 : ! Do it in 3 STEPs:
1895 : ! STEP1: Compute grad of cwavef and Laplacian of cwavef
1896 212256 : ABI_MALLOC(gcwavef1,(2,npw_k*ndat,3))
1897 106128 : ABI_MALLOC(lcwavef1,(2,npw_k*ndat))
1898 158683836 : gcwavef1 = zero; lcwavef1 = zero
1899 : !!$OMP PARALLEL DO
1900 109248 : do idat=1,ndat
1901 13315213 : do ipw=1,npw_k
1902 : ! convert k + G from reduced coords to Cartesian
1903 250913335 : kg_k_cart_vec = two_pi*MATMUL(gprimd,kpt(1:3)+kg_k(1:3,ipw))
1904 : ! form \grad\psi = i(k + G) \psi in Cartesian frame
1905 52823860 : gcwavef1(1,ipw+(idat-1)*npw_k,1:3)= cwavef1(2,ipw+(idat-1)*npw_k)*kg_k_cart_vec(1:3)
1906 52823860 : gcwavef1(2,ipw+(idat-1)*npw_k,1:3)= -cwavef1(1,ipw+(idat-1)*npw_k)*kg_k_cart_vec(1:3)
1907 : ! form \nabla^2\psi = -|k + G|^2 \psi
1908 : lcwavef1(1:2,ipw+(idat-1)*npw_k)=&
1909 79291974 : &lcwavef1(1:2,ipw+(idat-1)*npw_k)-cwavef1(1:2,ipw+(idat-1)*npw_k)*DOT_PRODUCT(kg_k_cart_vec,kg_k_cart_vec)
1910 : end do
1911 : end do
1912 : ! STEP2: Compute (vxctaulocal)*(Laplacian of cwavef) and add it to ghc
1913 : call fourwf(1,vxctaulocal(:,:,:,:,1),lcwavef1,ghc1,work,gbound_k,gbound_k,&
1914 : & istwf_k,kg_k,kg_k,mgfft,mpi_enreg,ndat,ngfft,npw_k,npw_k,n4,n5,n6,2,&
1915 53064 : & tim_fourwf,weight,weight,gpu_option=gpu_option)
1916 : !!$OMP PARALLEL DO
1917 109248 : do idat=1,ndat
1918 13315213 : do ipw=1,npw_k
1919 39674079 : ghc_mGGA(:,ipw+(idat-1)*my_nspinor*npw_k)=ghc_mGGA(:,ipw+(idat-1)*my_nspinor*npw_k)-half*ghc1(:,ipw+(idat-1)*npw_k)
1920 : end do
1921 : end do
1922 53064 : ABI_FREE(lcwavef1)
1923 : ! STEP3: Compute (grad components of vxctaulocal)*(grad components of cwavef)
1924 212256 : do idir=1,3
1925 : call fourwf(1,vxctaulocal(:,:,:,:,1+idir),gcwavef1(:,:,idir),ghc1,work,gbound_k,gbound_k,&
1926 : istwf_k,kg_k,kg_k,mgfft,mpi_enreg,ndat,ngfft,npw_k,npw_k,n4,n5,n6,2,&
1927 159192 : & tim_fourwf,weight,weight,gpu_option=gpu_option)
1928 : !!$OMP PARALLEL DO
1929 380808 : do idat=1,ndat
1930 39945639 : do ipw=1,npw_k
1931 119022237 : ghc_mGGA(:,ipw+(idat-1)*my_nspinor*npw_k) = ghc_mGGA(:,ipw+(idat-1)*my_nspinor*npw_k)-half*ghc1(:,ipw+(idat-1)*npw_k)
1932 : end do
1933 : end do
1934 : end do ! idir
1935 53064 : ABI_FREE(gcwavef1)
1936 53064 : ABI_FREE(ghc1)
1937 :
1938 : end if ! spin 1 treated by this proc
1939 :
1940 53064 : if (nspinor2TreatedByThisProc) then
1941 :
1942 106128 : ABI_MALLOC(ghc2,(2,npw_k*ndat))
1943 :
1944 : ! Do it in 3 STEPs:
1945 : ! STEP1: Compute grad of cwavef and Laplacian of cwavef
1946 212256 : ABI_MALLOC(gcwavef2,(2,npw_k*ndat,3))
1947 106128 : ABI_MALLOC(lcwavef2,(2,npw_k*ndat))
1948 : !!$OMP PARALLEL DO
1949 158683836 : gcwavef2 = zero; lcwavef2 = zero
1950 109248 : do idat=1,ndat
1951 13315213 : do ipw=1,npw_k
1952 : ! convert k + G from reduced coords to Cartesian
1953 250913335 : kg_k_cart_vec = two_pi*MATMUL(gprimd,kpt(1:3)+kg_k(1:3,ipw))
1954 : ! form \grad\psi = i(k + G) \psi in Cartesian frame
1955 52823860 : gcwavef2(1,ipw+(idat-1)*npw_k,1:3)= cwavef2(2,ipw+(idat-1)*npw_k)*kg_k_cart_vec(1:3)
1956 52823860 : gcwavef2(2,ipw+(idat-1)*npw_k,1:3)= -cwavef2(1,ipw+(idat-1)*npw_k)*kg_k_cart_vec(1:3)
1957 : ! form \nabla^2\psi = -|k + G|^2 \psi
1958 : lcwavef2(1:2,ipw+(idat-1)*npw_k)=&
1959 79291974 : &lcwavef2(1:2,ipw+(idat-1)*npw_k)-cwavef2(1:2,ipw+(idat-1)*npw_k)*DOT_PRODUCT(kg_k_cart_vec,kg_k_cart_vec)
1960 : end do
1961 : end do
1962 : ! STEP2: Compute (vxctaulocal)*(Laplacian of cwavef) and add it to ghc
1963 : call fourwf(1,vxctaulocal(:,:,:,:,1),lcwavef2,ghc2,work,gbound_k,gbound_k,&
1964 : & istwf_k,kg_k,kg_k,mgfft,mpi_enreg,ndat,ngfft,npw_k,npw_k,n4,n5,n6,2,&
1965 53064 : & tim_fourwf,weight,weight,gpu_option=gpu_option)
1966 : !!$OMP PARALLEL DO
1967 109248 : do idat=1,ndat
1968 13315213 : do ipw=1,npw_k
1969 : ! original code
1970 : ! ghc_mGGA(:,ipw+(idat-1)*my_nspinor*npw_k)=ghc_mGGA(:,ipw+(idat-1)*my_nspinor*npw_k)-half*ghc2(:,ipw+(idat-1)*npw_k)
1971 : ! but this stores the spinor2 result in the spinor1 location. Should be stored with shift
1972 : ghc_mGGA(:,ipw+(idat-1)*my_nspinor*npw_k+shift)=ghc_mGGA(:,ipw+(idat-1)*my_nspinor*npw_k+shift)&
1973 39674079 : & -half*ghc2(:,ipw+(idat-1)*npw_k)
1974 : end do
1975 : end do
1976 53064 : ABI_FREE(lcwavef2)
1977 : ! STEP3: Compute sum of (grad components of vxctaulocal)*(grad components of cwavef)
1978 212256 : do idir=1,3
1979 : call fourwf(1,vxctaulocal(:,:,:,:,1+idir),gcwavef2(:,:,idir),ghc2,work,gbound_k,gbound_k,&
1980 : istwf_k,kg_k,kg_k,mgfft,mpi_enreg,ndat,ngfft,npw_k,npw_k,n4,n5,n6,2,&
1981 159192 : & tim_fourwf,weight,weight,gpu_option=gpu_option)
1982 : !!$OMP PARALLEL DO
1983 380808 : do idat=1,ndat
1984 39945639 : do ipw=1,npw_k
1985 : ! original code
1986 : ! ghc_mGGA(:,ipw+(idat-1)*my_nspinor*npw_k)=ghc_mGGA(:,ipw+(idat-1)*my_nspinor*npw_k)-half*ghc2(:,ipw+(idat-1)*npw_k)
1987 : ! but this stores the spinor2 result in the spinor1 location. Should be stored with shift
1988 : ghc_mGGA(:,ipw+(idat-1)*my_nspinor*npw_k+shift)=ghc_mGGA(:,ipw+(idat-1)*my_nspinor*npw_k+shift)&
1989 119022237 : & -half*ghc2(:,ipw+(idat-1)*npw_k)
1990 : end do
1991 : end do
1992 : end do ! idir
1993 :
1994 53064 : ABI_FREE(gcwavef2)
1995 53064 : ABI_FREE(ghc2)
1996 :
1997 : end if ! spin 2 treated by this proc
1998 :
1999 53064 : ABI_FREE(cwavef1)
2000 53064 : ABI_FREE(cwavef2)
2001 :
2002 : end if ! nspinortot
2003 :
2004 98528 : ABI_FREE(work)
2005 :
2006 : end subroutine getghc_mGGA
2007 : !!***
2008 :
2009 : !!****f* ABINIT/cwavef_double_rfft_trick_pack
2010 : !!
2011 : !! NAME
2012 : !! cwavef_double_rfft_trick_pack
2013 : !!
2014 : !! FUNCTION
2015 : !!
2016 : !! We have C(G)=C(-G)^* and D(G)=D(-G)^* and only G components are in memory (istwfk=2)
2017 : !! The Fourier transform is:
2018 : !! C(r) = sum_G e^(iGr) C(G) = sum_(G_z>=0,G/=0) 2 Re[e^(iGr) C(G)] + C(0)
2019 : !! so C(r) is a real function (same for D)
2020 : !! Here we construct:
2021 : !! E( G) = C(G) + i D(G)
2022 : !! E(-G) = C(G)^* + i D(G)^* (G/=0)
2023 : !! so:
2024 : !! E(r) = C(r) + i D(r)
2025 : !! In short, one can do only one FFT on E (with istwfk=1) and obtains the FFT of C and D (istwfk=2)
2026 : !!
2027 : !! INPUTS
2028 : !! cwavef(2,npw_k*my_nspinor*(2*ndat))=planewave coefficients of wavefunctioni (istwfk=2)
2029 : !! mpi_enreg=information about MPI parallelization
2030 : !! ndat=number of FFTs to perform in parall
2031 : !! npw_k=number of planewaves in basis for given k point (istwfk=2).
2032 : !!
2033 : !! OUTPUT
2034 : !! cwavef_fft(2,npw_fft*my_nspinor*ndat)=planewave coefficients of wavefunction (istwfk=1)
2035 : !!
2036 : !! SOURCE
2037 : !!
2038 16912 : subroutine cwavef_double_rfft_trick_pack(cwavef,cwavef_fft,me_g0,ndat,npw_k)
2039 :
2040 : !Arguments ------------------------------------
2041 : !scalars
2042 : integer,intent(in) :: ndat,npw_k,me_g0
2043 : !arrays
2044 : real(dp),intent(in) :: cwavef(:,:)
2045 : real(dp),intent(out) :: cwavef_fft(:,:)
2046 : !Local variables-------------------------------
2047 : !scalars
2048 : integer :: idat,i0,ib1,ib2,npw_fft,ndat_
2049 : logical :: ndat_is_odd
2050 :
2051 16912 : ndat_ = ndat / 2
2052 16912 : ndat_is_odd=.False.
2053 16912 : if (modulo(ndat,2)/=0) then
2054 0 : ndat_=ndat_+1
2055 0 : ndat_is_odd=.True.
2056 : end if
2057 :
2058 16912 : npw_fft=2*npw_k
2059 16912 : i0=1
2060 16912 : if (me_g0==1) then! Do not include G=(0,0,0) twice
2061 16912 : npw_fft=npw_fft-1
2062 16912 : i0=2
2063 : end if
2064 :
2065 16912 : if (size(cwavef,1)/=2) then
2066 0 : ABI_BUG('wrong size for cwavef (dim 1)')
2067 : end if
2068 16912 : if (ndat_is_odd) then
2069 0 : if (size(cwavef,2)/=npw_k*(2*ndat_-1)) then
2070 0 : ABI_BUG('wrong size for cwavef (dim 2) (odd)')
2071 : end if
2072 : else
2073 16912 : if (size(cwavef,2)/=npw_k*2*ndat_) then
2074 0 : ABI_BUG('wrong size for cwavef (dim 2)')
2075 : end if
2076 : end if
2077 16912 : if (size(cwavef_fft,1)/=2.or.size(cwavef_fft,2)/=npw_fft*ndat_) then
2078 0 : ABI_BUG('wrong size for cwavef_fft')
2079 : end if
2080 :
2081 106164 : do idat=1,ndat_
2082 89252 : ib1=(idat-1)*npw_fft ! band shift for cwavef_fft
2083 89252 : ib2=(idat-1)*2*npw_k ! band shift for cwavef
2084 106164 : if (.not.ndat_is_odd.or.idat<ndat_) then
2085 : ! E(G) = C(G) + i D(G)
2086 : cwavef_fft(1,1+ib1:npw_k+ib1) = cwavef(1,1+ib2 : npw_k+ib2) &
2087 68960932 : -cwavef(2,1+npw_k+ib2:2*npw_k+ib2)
2088 : cwavef_fft(2,1+ib1:npw_k+ib1) = cwavef(2,1+ib2 : npw_k+ib2) &
2089 68960932 : +cwavef(1,1+npw_k+ib2:2*npw_k+ib2)
2090 : ! E(-G) = C(G)^* + i D(G)^* (G/=0)
2091 : cwavef_fft(1,1+npw_k+ib1:npw_fft+ib1) = cwavef(1,i0 +ib2: npw_k+ib2) &
2092 68871680 : +cwavef(2,i0+npw_k+ib2:2*npw_k+ib2)
2093 : cwavef_fft(2,1+npw_k+ib1:npw_fft+ib1) =-cwavef(2,i0 +ib2: npw_k+ib2) &
2094 68871680 : +cwavef(1,i0+npw_k+ib2:2*npw_k+ib2)
2095 : else ! idat=ndat_ and ndat_is_odd : the vector D does not exist
2096 : ! E(G) = C(G)
2097 0 : cwavef_fft(1,1+ib1:npw_k+ib1) = cwavef(1,1+ib2:npw_k+ib2)
2098 0 : cwavef_fft(2,1+ib1:npw_k+ib1) = cwavef(2,1+ib2:npw_k+ib2)
2099 : ! E(-G) = C(G)^* (G/=0)
2100 0 : cwavef_fft(1,1+npw_k+ib1:npw_fft+ib1) = cwavef(1,i0+ib2:npw_k+ib2)
2101 0 : cwavef_fft(2,1+npw_k+ib1:npw_fft+ib1) =-cwavef(2,i0+ib2:npw_k+ib2)
2102 : end if
2103 : end do
2104 :
2105 16912 : end subroutine cwavef_double_rfft_trick_pack
2106 : !!***
2107 :
2108 : !!****f* ABINIT/cwavef_double_rfft_trick_unpack
2109 : !!
2110 : !! NAME
2111 : !! cwavef_double_rfft_trick_unpack
2112 : !!
2113 : !! FUNCTION
2114 : !!
2115 : !! From the "cwavef_double_rfft_trick_pack" routine we have:
2116 : !! E( G) = C(G) + i D(G)
2117 : !! E(-G) = C(G)^* + i D(G)^* (G/=0)
2118 : !! Here we compute:
2119 : !! C(G) = ( E(G) + E(-G)^* ) / 2 (G/=0)
2120 : !! D(G) = ( iE(-G)^* - iE(G)) / 2 (G/=0)
2121 : !! and:
2122 : !! C(0) = Re(E(0))
2123 : !! D(0) = Im(E(0))
2124 : !!
2125 : !! INPUTS
2126 : !! cwavef_fft(2,npw_fft*my_nspinor*ndat_)=planewave coefficients of wavefunction (istwfk=1)
2127 : !! mpi_enreg=information about MPI parallelization
2128 : !! ndat=number of FFTs to perform in parall
2129 : !! npw_k=number of planewaves in basis for given k point (istwfk=2).
2130 : !!
2131 : !! OUTPUT
2132 : !! cwavef(2,npw_fft*my_nspinor*(2*ndat))=planewave coefficients of wavefunction (istwfk=2)
2133 : !!
2134 : !! SOURCE
2135 : !!
2136 16912 : subroutine cwavef_double_rfft_trick_unpack(cwavef,cwavef_fft,me_g0,ndat,npw_k)
2137 :
2138 : !Arguments ------------------------------------
2139 : !scalars
2140 : integer,intent(in) :: ndat,npw_k,me_g0
2141 : !arrays
2142 : real(dp),intent(out) :: cwavef(:,:)
2143 : real(dp),intent(in) :: cwavef_fft(:,:)
2144 : !Local variables-------------------------------
2145 : !scalars
2146 : integer :: idat,i0,ib1,ib2,npw_fft,ndat_
2147 : logical :: ndat_is_odd
2148 :
2149 16912 : ndat_ = ndat / 2
2150 16912 : ndat_is_odd=.False.
2151 16912 : if (modulo(ndat,2)/=0) then
2152 0 : ndat_=ndat_+1
2153 0 : ndat_is_odd=.True.
2154 : end if
2155 :
2156 16912 : npw_fft=2*npw_k
2157 16912 : i0=1
2158 16912 : if (me_g0==1) then! Do not include G=(0,0,0) twice
2159 16912 : npw_fft=npw_fft-1
2160 16912 : i0=2
2161 : end if
2162 :
2163 16912 : if (size(cwavef,1)/=2) then
2164 0 : ABI_BUG('wrong size for cwavef (dim 1)')
2165 : end if
2166 16912 : if (ndat_is_odd) then
2167 0 : if (size(cwavef,2)/=npw_k*(2*ndat_-1)) then
2168 0 : ABI_BUG('wrong size for cwavef (dim 2) (odd)')
2169 : end if
2170 : else
2171 16912 : if (size(cwavef,2)/=npw_k*2*ndat_) then
2172 0 : ABI_BUG('wrong size for cwavef (dim 2)')
2173 : end if
2174 : end if
2175 16912 : if (size(cwavef_fft,1)/=2.or.size(cwavef_fft,2)/=npw_fft*ndat_) then
2176 0 : ABI_BUG('wrong size for cwavef_fft')
2177 : end if
2178 :
2179 106164 : do idat=1,ndat_
2180 89252 : ib1=(idat-1)*npw_fft ! band shift for cwavef_fft
2181 89252 : ib2=(idat-1)*2*npw_k ! band shift for cwavef
2182 : ! C(G) = ( E(G) + E(-G)^* ) / 2 (factor 1/2 will be applied later)
2183 : cwavef(1,i0+ib2:npw_k+ib2) = cwavef_fft(1,i0 +ib1:npw_k +ib1) & !+Re(E( G))
2184 68871680 : +cwavef_fft(1,1 +npw_k+ib1:npw_fft+ib1) !+Re(E(-G))
2185 : cwavef(2,i0+ib2:npw_k+ib2) = cwavef_fft(2,i0 +ib1:npw_k +ib1) & !+Im(E( G))
2186 68871680 : -cwavef_fft(2,1 +npw_k+ib1:npw_fft+ib1) !-Im(E(-G))
2187 89252 : if (.not.ndat_is_odd.or.idat<ndat_) then
2188 : ! D(G) = ( iE(-G)^* - iE(G) ) / 2 (factor 1/2 will be applied later)
2189 : cwavef(1,i0+npw_k+ib2:2*npw_k+ib2) = cwavef_fft(2,i0 +ib1:npw_k +ib1) & !+Im(E( G))
2190 68871680 : +cwavef_fft(2,1 +npw_k+ib1:npw_fft+ib1) !+Im(E(-G))
2191 : cwavef(2,i0+npw_k+ib2:2*npw_k+ib2) =-cwavef_fft(1,i0 +ib1:npw_k +ib1) & !-Re(E( G))
2192 68871680 : +cwavef_fft(1,1 +npw_k+ib1:npw_fft+ib1) !+Re(E(-G))
2193 : end if
2194 106164 : if (me_g0==1) then
2195 : ! Compute C(G=0) and D(G=0) and multiply by 2 as we apply 1/2 to the whole array shortly afterwards
2196 : ! C(G=0) = Re(E(G=0))
2197 89252 : cwavef(1,1+ib2) = two*cwavef_fft(1,1+ib1)
2198 89252 : cwavef(2,1+ib2) = zero
2199 89252 : if (.not.ndat_is_odd.or.idat<ndat_) then
2200 : ! D(G=0) = Im(E(G=0))
2201 89252 : cwavef(1,1+npw_k+ib2) = two*cwavef_fft(2,1+ib1)
2202 89252 : cwavef(2,1+npw_k+ib2) = zero
2203 : end if
2204 : end if
2205 :
2206 : end do
2207 :
2208 413246992 : cwavef(:,:) = half*cwavef(:,:)
2209 :
2210 16912 : end subroutine cwavef_double_rfft_trick_unpack
2211 : !!***
2212 :
2213 : !!****f* ABINIT/getgsc
2214 : !! NAME
2215 : !! getgsc
2216 : !!
2217 : !! FUNCTION
2218 : !! Compute <G|S|C> for all input vectors |Cnk> at a given k-point,
2219 : !! OR for one input vector |Cnk>.
2220 : !! |Cnk> are expressed in reciprocal space.
2221 : !! S is the overlap operator between |Cnk> (used for PAW).
2222 : !!
2223 : !! INPUTS
2224 : !! cg(2,mcg)=planewave coefficients of wavefunctions
2225 : !! cprj(natom,mcprj)= wave functions projected with non-local projectors: cprj=<p_i|Cnk>
2226 : !! gs_ham <type(gs_hamiltonian_type)>=all data for the Hamiltonian at k+q
2227 : !! ibg=shift to be applied on the location of data in the array cprj (beginning of current k-point)
2228 : !! icg=shift to be applied on the location of data in the array cg (beginning of current k-point)
2229 : !! igsc=shift to be applied on the location of data in the array gsc (beginning of current k-point)
2230 : !! ikpt,isppol=indexes of current (spin.kpoint)
2231 : !! mcg=second dimension of the cg array
2232 : !! mcprj=second dimension of the cprj array
2233 : !! mgsc=second dimension of the gsc array
2234 : !! mpi_enreg=information about MPI parallelization
2235 : !! ndat=number of bands to compute in parallel
2236 : !! natom=number of atoms in unit cell.
2237 : !! nband= if positive: number of bands at this k point for that spin polarization
2238 : !! if negative: abs(nband) is the index of the only band to be computed
2239 : !! npw_k=number of planewaves in basis for given k point.
2240 : !! nspinor=number of spinorial components of the wavefunctions
2241 : !! [select_k]=optional, option governing the choice of k points to be used.
2242 : !! gs_ham datastructure contains quantities needed to apply overlap operator
2243 : !! in reciprocal space between 2 kpoints, k and k^prime (equal in most cases);
2244 : !! if select_k=1, <k^prime|S|k> is applied [default]
2245 : !! if select_k=2, <k|S|k^prime> is applied
2246 : !! if select_k=3, <k|S|k> is applied
2247 : !! if select_k=4, <k^prime|S|k^prime> is applied
2248 : !!
2249 : !! OUTPUT
2250 : !! gsc(2,mgsc)= <g|S|Cnk> or <g|S^(1)|Cnk> (S=overlap)
2251 : !!
2252 : !! SOURCE
2253 :
2254 179581 : subroutine getgsc(cg,cprj,gs_ham,gsc,ibg,icg,igsc,ikpt,isppol,&
2255 : & mcg,mcprj,mgsc,mpi_enreg,ndat,natom,nband,npw_k,nspinor,select_k)
2256 :
2257 : !Arguments ------------------------------------
2258 : !scalars
2259 : integer,intent(in) :: ibg,icg,igsc,ikpt,isppol,mcg,mcprj
2260 : integer,intent(in) :: mgsc,natom,nband,npw_k,nspinor,ndat
2261 : !TODO : may be needed to distribute cprj over band procs
2262 : ! integer,intent(in) :: mband_mem
2263 : integer,intent(in),optional :: select_k
2264 : type(MPI_type),intent(in) :: mpi_enreg
2265 : type(gs_hamiltonian_type),intent(inout),target :: gs_ham
2266 : !arrays
2267 : real(dp),intent(in), target :: cg(2,mcg)
2268 : real(dp),intent(out), target :: gsc(2,mgsc)
2269 : type(pawcprj_type),intent(in) :: cprj(natom,mcprj)
2270 :
2271 : !Local variables-------------------------------
2272 : !scalars
2273 : integer :: choice,cpopt,dimenl1,dimenl2,iband,iband1,iband2,index_cg,index_cprj
2274 : integer :: index_gsc,me,my_nspinor,my_ndat,paw_opt,select_k_,signs,tim_nonlop,useylm
2275 : !character(len=500) :: msg
2276 : !arrays
2277 359162 : real(dp) :: enlout_dum(ndat),tsec(2)
2278 179581 : real(dp), contiguous, pointer :: cwavef(:,:),scwavef(:,:)
2279 179581 : type(pawcprj_type),allocatable :: cwaveprj(:,:)
2280 : ! *********************************************************************
2281 :
2282 : DBG_ENTER("COLL")
2283 :
2284 : !Compatibility tests
2285 179581 : my_nspinor=max(1,nspinor/mpi_enreg%nproc_spinor)
2286 66816 : my_ndat=ndat; if(nband<1) my_ndat=1
2287 179581 : if(gs_ham%usepaw==0) then
2288 0 : ABI_BUG('Only compatible with PAW (usepaw=1) !')
2289 : end if
2290 179581 : if(nband<0.and.(mcg<npw_k*my_nspinor.or.mgsc<npw_k*my_nspinor.or.mcprj<my_nspinor)) then
2291 0 : ABI_BUG('Invalid value for mcg, mgsc or mcprj !')
2292 : end if
2293 :
2294 : !Keep track of total time spent in getgsc:
2295 179581 : call timab(565,1,tsec)
2296 :
2297 179581 : if(gs_ham%gpu_option==ABI_GPU_DISABLED) then
2298 273119845 : gsc = zero
2299 : else if(gs_ham%gpu_option==ABI_GPU_DISABLED) then
2300 : #ifdef HAVE_OPENMP_OFFLOAD
2301 : call gpu_set_to_zero(gsc,int(2,c_size_t)*mgsc)
2302 : #endif
2303 : end if
2304 :
2305 : !Prepare some data
2306 179581 : if (gs_ham%usecprj==1) then
2307 804010 : ABI_MALLOC(cwaveprj,(natom,my_nspinor*my_ndat))
2308 112765 : call pawcprj_alloc(cwaveprj,0,gs_ham%dimcprj)
2309 : else
2310 66816 : ABI_MALLOC(cwaveprj,(0,0))
2311 : end if
2312 179581 : dimenl1=gs_ham%dimekb1;dimenl2=natom;tim_nonlop=0
2313 179581 : choice=1;signs=2;cpopt=-1+3*gs_ham%usecprj;paw_opt=3;useylm=1
2314 179581 : select_k_=1;if (present(select_k)) select_k_=select_k
2315 179581 : me=mpi_enreg%me_kpt
2316 :
2317 : !Loop over bands
2318 179581 : index_cprj=ibg;index_cg=icg;index_gsc=igsc
2319 179581 : if (nband>0) then
2320 : iband1=1;iband2=nband
2321 : !only do 1 band in case nband < 0 (the |nband|th one)
2322 66816 : else if (nband<0) then
2323 66816 : iband1=abs(nband);iband2=iband1
2324 66816 : index_cprj=index_cprj+(iband1-1)*my_nspinor
2325 66816 : index_cg =index_cg +(iband1-1)*npw_k*my_nspinor
2326 66816 : index_gsc =index_gsc +(iband1-1)*npw_k*my_nspinor
2327 : end if
2328 :
2329 848129 : do iband=iband1,iband2,my_ndat
2330 :
2331 668548 : if (mpi_enreg%proc_distrb(ikpt,iband,isppol)/=me.and.nband>0) then
2332 : ! No longer needed 28/03/2020 to parallelize memory
2333 : ! gsc(:,1+index_gsc:npw_k*my_nspinor+index_gsc)=zero
2334 : ! index_gsc=index_gsc+npw_k*my_nspinor
2335 : !index_cprj=index_cprj+my_nspinor
2336 : !index_cg=index_cg+npw_k*my_nspinor
2337 :
2338 : cycle
2339 : end if
2340 :
2341 : ! Retrieve WF at (n,k)
2342 665380 : cwavef(1:2,1:npw_k*my_nspinor*my_ndat) => cg(:,1+index_cg:npw_k*my_nspinor*my_ndat+index_cg)
2343 665380 : scwavef(1:2,1:npw_k*my_nspinor*my_ndat) => gsc(:,1+index_gsc:npw_k*my_nspinor*my_ndat+index_gsc)
2344 665380 : if (gs_ham%usecprj==1) then
2345 598564 : call pawcprj_copy(cprj(:,1+index_cprj:my_nspinor*my_ndat+index_cprj),cwaveprj)
2346 : end if
2347 :
2348 : ! Compute <g|S|Cnk>
2349 : call nonlop(choice,cpopt,cwaveprj,enlout_dum,gs_ham,0,(/zero/),mpi_enreg,my_ndat,1,paw_opt,&
2350 665380 : & signs,scwavef,tim_nonlop,cwavef,cwavef,select_k=select_k_)
2351 :
2352 :
2353 : ! End of loop over bands
2354 665380 : index_cprj=index_cprj+my_nspinor*my_ndat
2355 665380 : index_cg=index_cg+npw_k*my_nspinor*my_ndat
2356 848129 : index_gsc=index_gsc+npw_k*my_nspinor*my_ndat
2357 : end do
2358 :
2359 : !Memory deallocation
2360 179581 : if (gs_ham%usecprj==1) then
2361 112765 : call pawcprj_free(cwaveprj)
2362 : end if
2363 416652 : ABI_FREE(cwaveprj)
2364 :
2365 179581 : call timab(565,2,tsec)
2366 :
2367 : DBG_EXIT("COLL")
2368 :
2369 359162 : end subroutine getgsc
2370 : !!***
2371 :
2372 : !!****f* ABINIT/multithreaded_getghc
2373 : !!
2374 : !! NAME
2375 : !! multithreaded_getghc
2376 : !!
2377 : !! FUNCTION
2378 : !!
2379 : !! INPUTS
2380 : !! cpopt=flag defining the status of cwaveprj%cp(:)=<Proj_i|Cnk> scalars (PAW only)
2381 : !! (same meaning as in nonlop.F90 routine)
2382 : !! if cpopt=-1, <p_lmn|in> (and derivatives) are computed here (and not saved)
2383 : !! if cpopt= 0, <p_lmn|in> are computed here and saved
2384 : !! if cpopt= 1, <p_lmn|in> and first derivatives are computed here and saved
2385 : !! if cpopt= 2 <p_lmn|in> are already in memory;
2386 : !! if cpopt= 3 <p_lmn|in> are already in memory; first derivatives are computed here and saved
2387 : !! if cpopt= 4 <p_lmn|in> and first derivatives are already in memory;
2388 : !! cwavef(2,npw*my_nspinor*ndat)=planewave coefficients of wavefunction.
2389 : !! gs_ham <type(gs_hamiltonian_type)>=all data for the Hamiltonian to be applied
2390 : !! lambda=factor to be used when computing <G|H-lambda.S|C> - only for sij_opt=-1
2391 : !! Typically lambda is the eigenvalue (or its guess)
2392 : !! mpi_enreg=information about MPI parallelization
2393 : !! ndat=number of FFT to do in parallel
2394 : !! prtvol=control print volume and debugging output
2395 : !! sij_opt= -PAW ONLY- if 0, only matrix elements <G|H|C> have to be computed
2396 : !! (S=overlap) if 1, matrix elements <G|S|C> have to be computed in gsc in addition to ghc
2397 : !! if -1, matrix elements <G|H-lambda.S|C> have to be computed in ghc (gsc not used)
2398 : !! tim_getghc=timing code of the calling subroutine(can be set to 0 if not attributed)
2399 : !! type_calc= option governing which part of Hamitonian is to be applied:
2400 : !! 0: whole Hamiltonian
2401 : !! 1: local part only
2402 : !! 2: non-local+kinetic only (added to the existing Hamiltonian)
2403 : !! 3: local + kinetic only (added to the existing Hamiltonian)
2404 : !! ===== Optional inputs =====
2405 : !! [kg_fft_k(3,:)]=optional, (k+G) vector coordinates to be used for the FFT transformation
2406 : !! instead of the one contained in gs_ham datastructure.
2407 : !! Typically used for real WF (in parallel) which are FFT-transformed 2 by 2.
2408 : !! [kg_fft_kp(3,:)]=optional, (k^prime+G) vector coordinates to be used for the FFT transformation
2409 : !! [select_k]=optional, option governing the choice of k points to be used.
2410 : !! gs_ham datastructure contains quantities needed to apply Hamiltonian
2411 : !! in reciprocal space between 2 kpoints, k and k^prime (equal in most cases);
2412 : !! if select_k=1, <k^prime|H|k> is applied [default]
2413 : !! if select_k=2, <k|H|k^prime> is applied
2414 : !! if select_k=3, <k|H|k> is applied
2415 : !! if select_k=4, <k^prime|H|k^prime> is applied
2416 : !!
2417 : !! OUTPUT
2418 : !! ghc(2,npw*my_nspinor*ndat)=matrix elements <G|H|C> (if sij_opt>=0)
2419 : !! or <G|H-lambda.S|C> (if sij_opt=-1)
2420 : !! gvnlxc(2,npw*my_nspinor*ndat)=matrix elements <G|Vnonlocal|C> (if sij_opt>=0)
2421 : !! or <G|Vnonlocal-lambda.S|C> (if sij_opt=-1)
2422 : !! if (sij_opt=1)
2423 : !! gsc(2,npw*my_nspinor*ndat)=matrix elements <G|S|C> (S=overlap).
2424 : !!
2425 : !! SIDE EFFECTS
2426 : !! cwaveprj(natom,my_nspinor*(1+cpopt)*ndat)= wave function projected on nl projectors (PAW only)
2427 : !!
2428 : !! SOURCE
2429 :
2430 2238536 : subroutine multithreaded_getghc(cpopt,cwavef,cwaveprj,ghc,gsc,gs_ham,gvnlxc,lambda,mpi_enreg,ndat,&
2431 : & prtvol,sij_opt,tim_getghc,type_calc,&
2432 1119268 : & kg_fft_k,kg_fft_kp,select_k,filter_dilatmx_loc) ! optional arguments
2433 :
2434 : #ifdef HAVE_OPENMP
2435 : use omp_lib
2436 : #endif
2437 :
2438 : !Arguments ------------------------------------
2439 : !scalars
2440 : logical,intent(in),optional :: filter_dilatmx_loc
2441 : integer,intent(in) :: cpopt,ndat, prtvol
2442 : integer,intent(in) :: sij_opt,tim_getghc,type_calc
2443 : integer,intent(in),optional :: select_k
2444 : real(dp),intent(in) :: lambda
2445 : type(MPI_type),intent(in) :: mpi_enreg
2446 : type(gs_hamiltonian_type),intent(inout),target :: gs_ham
2447 : !arrays
2448 : integer,intent(in),optional,target :: kg_fft_k(:,:),kg_fft_kp(:,:)
2449 : real(dp),intent(out),target :: gsc(:,:)
2450 : real(dp),intent(inout) :: cwavef(:,:)
2451 : real(dp),intent(out) :: ghc(:,:),gvnlxc(:,:)
2452 : type(pawcprj_type),intent(inout),target :: cwaveprj(:,:)
2453 :
2454 : !Local variables-------------------------------
2455 : !scalars
2456 : logical :: filter_dilatmx_loc_
2457 : integer :: firstelt, firstprj, lastelt, lastprj,usegvnlxc,usegsc
2458 : integer :: nthreads,fftalga
2459 : integer :: ithread
2460 : integer :: chunk
2461 : integer :: residuchunk
2462 : integer :: firstband
2463 : integer :: lastband
2464 : integer :: spacedim, spacedim_prj
2465 : logical :: fftw3_use_lib_threads_sav
2466 : integer :: select_k_default
2467 : ! *************************************************************************
2468 :
2469 1119268 : select_k_default = 1; if (present(select_k)) select_k_default = select_k
2470 1119268 : filter_dilatmx_loc_ = .true.; if ( present(filter_dilatmx_loc) ) filter_dilatmx_loc_ = filter_dilatmx_loc
2471 :
2472 1119268 : spacedim = size(cwavef ,dim=2)/ndat
2473 1119268 : spacedim_prj = size(cwaveprj,dim=2)/ndat
2474 :
2475 1119268 : nthreads = xomp_get_num_threads(open_parallel=.True.)
2476 1119268 : fftalga = gs_ham%ngfft(7)/100
2477 1119268 : if (fftalga==FFT_SG.and.nthreads>1.and.ndat>1) then
2478 0 : ABI_ERROR("fftalg=1XX is not thread-safe, so it cannot be used in multi-threaded hamiltonian with nthreads>1 and ndat>1.")
2479 : end if
2480 :
2481 : ! Disabling multithreading for GPU variants (getghc_ompgpu is not thread-safe for now)
2482 : !$omp parallel default (none) &
2483 : !$omp& private(ithread,nthreads,chunk,firstband,lastband,residuchunk,firstelt,lastelt), &
2484 : !$omp& private(firstprj,lastprj,usegvnlxc,usegsc,fftw3_use_lib_threads_sav), &
2485 : !$omp& shared(cwavef,ghc,gsc, gvnlxc,spacedim,spacedim_prj,ndat,kg_fft_k,kg_fft_kp,gs_ham,cwaveprj,mpi_enreg), &
2486 : !$omp& shared(gemm_nonlop_use_gemm), &
2487 : !$omp& firstprivate(cpopt,lambda,prtvol,sij_opt,tim_getghc,type_calc,select_k_default,filter_dilatmx_loc_) &
2488 : !$omp& IF(gs_ham%gpu_option==ABI_GPU_DISABLED .and. .not. gemm_nonlop_use_gemm)
2489 1119268 : ithread = 0
2490 1119268 : nthreads = 1
2491 1119268 : fftw3_use_lib_threads_sav = .false.
2492 : if(gs_ham%gpu_option==ABI_GPU_DISABLED .and. .not. gemm_nonlop_use_gemm) then
2493 : #ifdef HAVE_OPENMP
2494 : ithread = omp_get_thread_num()
2495 : nthreads = omp_get_num_threads()
2496 : !Ensure that libs are used without threads (mkl, openblas, fftw3, ...)
2497 : #ifdef HAVE_LINALG_MKL_THREADS
2498 : call mkl_set_num_threads(1)
2499 : #endif
2500 : !LB-23/07/24: OpenBLAS detects parallel sections automatically. To comment this line improves performances for some cases.
2501 : !#ifdef HAVE_LINALG_OPENBLAS_THREADS
2502 : ! call openblas_set_num_threads(1)
2503 : !#endif
2504 : #ifdef HAVE_LINALG_NVPL_THREADS
2505 : call nvpl_blas_set_num_threads(1)
2506 : #endif
2507 : #ifdef HAVE_FFTW3_THREADS
2508 : fftw3_use_lib_threads_sav=(.not.fftw3_spawn_threads_here(nthreads,nthreads))
2509 : call fftw3_use_lib_threads(.false.)
2510 : #endif
2511 : #endif
2512 : end if
2513 1119268 : chunk = ndat/nthreads ! Divide by 2 to construct chunk of even number of bands
2514 1119268 : residuchunk = ndat - nthreads*chunk
2515 : if ( ithread < nthreads-residuchunk ) then
2516 : firstband = ithread*chunk+1
2517 : lastband = (ithread+1)*chunk
2518 : else
2519 : firstband = (nthreads-residuchunk)*chunk + ( ithread -(nthreads-residuchunk) )*(chunk+1) +1
2520 : lastband = firstband+chunk
2521 : end if
2522 1119268 : usegvnlxc=1
2523 3357804 : if (size(gvnlxc)<=1) usegvnlxc=0
2524 1119268 : usegsc=0
2525 1119268 : if (gs_ham%usepaw==1.and.sij_opt==1) usegsc=1
2526 :
2527 1119268 : if ( lastband /= 0 ) then
2528 1119268 : firstelt = (firstband-1)*spacedim+1
2529 1119268 : firstprj = (firstband-1)*spacedim_prj+1
2530 1119268 : lastelt = lastband*spacedim
2531 1119268 : lastprj = lastband*spacedim_prj
2532 : ! Don't know how to manage optional arguments .... :(
2533 1119268 : if ( present(kg_fft_k) ) then
2534 3274 : if (present(kg_fft_kp)) then
2535 : call getghc(cpopt,cwavef(:,firstelt:lastelt),cwaveprj(:,firstprj:lastprj),&
2536 : & ghc(:,firstelt:lastelt),gsc(:,firstelt:lastelt*usegsc),&
2537 : & gs_ham,gvnlxc(:,firstelt:lastelt*usegvnlxc),lambda, mpi_enreg,lastband-firstband+1,&
2538 : & prtvol,sij_opt,tim_getghc,type_calc,&
2539 0 : & select_k=select_k_default,kg_fft_k=kg_fft_k,kg_fft_kp=kg_fft_kp,filter_dilatmx_loc=filter_dilatmx_loc_)
2540 : else
2541 : call getghc(cpopt,cwavef(:,firstelt:lastelt),cwaveprj(:,firstprj:lastprj),&
2542 : & ghc(:,firstelt:lastelt),gsc(:,firstelt:lastelt*usegsc),&
2543 : & gs_ham,gvnlxc(:,firstelt:lastelt*usegvnlxc),lambda, mpi_enreg,lastband-firstband+1,&
2544 : & prtvol,sij_opt,tim_getghc,type_calc,&
2545 3274 : & select_k=select_k_default,kg_fft_k=kg_fft_k,filter_dilatmx_loc=filter_dilatmx_loc_)
2546 : end if
2547 : else
2548 1115994 : if (present(kg_fft_kp)) then
2549 : call getghc(cpopt,cwavef(:,firstelt:lastelt),cwaveprj(:,firstprj:lastprj),&
2550 : & ghc(:,firstelt:lastelt),gsc(:,firstelt:lastelt*usegsc),&
2551 : & gs_ham,gvnlxc(:,firstelt:lastelt*usegvnlxc),lambda, mpi_enreg,lastband-firstband+1,&
2552 : & prtvol,sij_opt,tim_getghc,type_calc,&
2553 0 : & select_k=select_k_default,kg_fft_kp=kg_fft_kp,filter_dilatmx_loc=filter_dilatmx_loc_)
2554 : else
2555 : call getghc(cpopt,cwavef(:,firstelt:lastelt),cwaveprj(:,firstprj:lastprj),&
2556 : & ghc(:,firstelt:lastelt),gsc(:,firstelt:lastelt*usegsc),&
2557 : & gs_ham,gvnlxc(:,firstelt:lastelt*usegvnlxc),lambda, mpi_enreg,lastband-firstband+1,&
2558 : & prtvol,sij_opt,tim_getghc,type_calc,&
2559 1115994 : & select_K=select_k_default,filter_dilatmx_loc=filter_dilatmx_loc_)
2560 : end if
2561 : end if
2562 : end if
2563 : if(gs_ham%gpu_option==ABI_GPU_DISABLED .and. .not. gemm_nonlop_use_gemm) then
2564 : #ifdef HAVE_OPENMP
2565 : !Restore libs behavior (mkl, openblas, fftw3, ...)
2566 : #ifdef HAVE_LINALG_MKL_THREADS
2567 : call mkl_set_num_threads(nthreads)
2568 : #endif
2569 : !LB-23/07/24: OpenBLAS detects parallel sections automatically. To comment this line improves performances for some cases.
2570 : !#ifdef HAVE_LINALG_OPENBLAS_THREADS
2571 : ! call openblas_set_num_threads(nthreads)
2572 : !#endif
2573 : #ifdef HAVE_LINALG_NVPL_THREADS
2574 : call nvpl_blas_set_num_threads(nthreads)
2575 : #endif
2576 : #ifdef HAVE_FFTW3_THREADS
2577 : call fftw3_use_lib_threads(fftw3_use_lib_threads_sav)
2578 : #endif
2579 : #endif
2580 : end if
2581 : !$omp end parallel
2582 :
2583 1119268 : end subroutine multithreaded_getghc
2584 : !!***
2585 :
2586 : end module m_getghc
2587 : !!***
|