Line data Source code
1 : !!****f* ABINIT/m_slicewf_cprj
2 : !! NAME
3 : !! m_slicewf_cprj
4 : !!
5 : !! FUNCTION
6 : !! This module contains a routine updating the whole wave functions at a given k-point,
7 : !! using the Spectrum Slicing filtering method (2021 implementation using xG abstraction layer)
8 : !! for a given spin-polarization, from a fixed hamiltonian
9 : !! but might also simply compute eigenvectors and eigenvalues at this k point.
10 : !! it will also update the matrix elements of the hamiltonian.
11 : !!
12 : !! COPYRIGHT
13 : !! Copyright (C) 2023-2025 ABINIT group (LB,IML)
14 : !! This file is distributed under the terms of the
15 : !! gnu general public license, see ~abinit/COPYING
16 : !! or http://www.gnu.org/copyleft/gpl.txt .
17 : !! for the initials of contributors, see ~abinit/doc/developers/contributors.txt .
18 : !!
19 : !! PARENTS
20 : !! vtowfk
21 : !!
22 : !! CHILDREN
23 : !!
24 : !! SOURCE
25 :
26 : #if defined HAVE_CONFIG_H
27 : #include "config.h"
28 : #endif
29 :
30 : #include "abi_common.h"
31 :
32 : module m_slicewf_cprj
33 :
34 : use defs_abitypes
35 : use defs_basis
36 : use m_abicore
37 : use m_errors
38 : use m_fstrings
39 : use m_time
40 : use m_xg
41 : use m_xg_nonlop
42 : use m_slice_cprj
43 : use m_invovl
44 :
45 : use m_dtset, only : dataset_type
46 : use m_hamiltonian, only : gs_hamiltonian_type
47 : use m_pawcprj, only : pawcprj_type
48 : use m_getghc, only : multithreaded_getghc
49 :
50 : use m_xg
51 : use m_xgTransposer
52 :
53 : use iso_c_binding, only: c_associated,c_loc,c_ptr,c_f_pointer
54 :
55 : use m_xmpi
56 : use m_xomp
57 : #ifdef HAVE_OPENMP
58 : use omp_lib
59 : #endif
60 :
61 : implicit none
62 :
63 : private
64 :
65 : integer, parameter :: l_tim_getghc=5
66 :
67 : ! For use in getghc_gsc1
68 : integer, save :: l_prtvol
69 : type(mpi_type),pointer,save :: l_mpi_enreg
70 : type(gs_hamiltonian_type),pointer,save :: l_gs_hamk
71 :
72 : public :: slicewf_cprj
73 :
74 : contains
75 : !!***
76 :
77 : !!****f* m_slicewf/slicewf_cprj
78 : !! NAME
79 : !! slicewf_cprj
80 : !!
81 : !! FUNCTION
82 : !! This routine updates the whole wave functions set at a given k-point,
83 : !! using the Spectrum Slicing method (2021 version using xG abstraction layer)
84 : !!
85 : !! INPUTS
86 : !! dtset= input variables for this dataset
87 : !! mpi_enreg= MPI-parallelisation information
88 : !! nband= number of bands at this k point
89 : !! npw= number of plane waves at this k point
90 : !! nspinor= number of spinorial components of the wavefunctions
91 : !! prtvol= control print volume and debugging
92 : !!
93 : !! OUTPUT
94 : !! eig(nband)= eigenvalues (hartree) for all bands
95 : !! enl_out(nband)= contribution of each band to the nl part of energy
96 : !! resid(nband)= residuals for each band
97 : !!
98 : !! SIDE EFFECTS
99 : !! cg(2,npw*nspinor*nband)= planewave coefficients of wavefunctions
100 : !! gs_hamk <type(gs_hamiltonian_type)>=all data for the hamiltonian at k
101 : !!
102 : !! SOURCE
103 :
104 0 : subroutine slicewf_cprj(cg,dtset,eig,occ,enl_out,gs_hamk,mpi_enreg,&
105 0 : & nband,npw,nspinor,prtvol,resid,xg_nonlop)
106 :
107 : !Arguments ------------------------------------
108 : integer,intent(in) :: nband,npw,prtvol,nspinor
109 : type(gs_hamiltonian_type),target,intent(inout) :: gs_hamk
110 : type(dataset_type) ,intent(in ) :: dtset
111 : type(mpi_type) ,target,intent(in) :: mpi_enreg
112 : real(dp) ,target,intent(inout) :: cg(2,nspinor*nband*npw)
113 : real(dp) ,target,intent( out) :: resid(nband)
114 : real(dp) ,intent( out) :: enl_out(nband)
115 : real(dp) ,target,intent( out) :: eig(nband)
116 : real(dp) ,target,intent(in ) :: occ(nband)
117 : type(xg_nonlop_t) , intent(in ) :: xg_nonlop
118 :
119 : !Local variables-------------------------------
120 :
121 : type(xgBlock_t) :: xgx0
122 : type(xg_t) :: cprj_xgx0
123 : type(xgBlock_t) :: xgeigen
124 : type(xgBlock_t) :: xgocc
125 : type(xgBlock_t) :: xgresidu
126 : type(xgBlock_t) :: xgenl
127 : type(xgBlock_t) :: xg_kin
128 0 : type(slice_t) :: slice
129 :
130 : logical :: paw
131 :
132 : integer :: space, space_cprj, blockdim, cprjdim, nband_cprj
133 : integer :: me_g0,me_g0_fft
134 :
135 : integer, parameter :: tim_slicewf = 2170
136 : double precision :: tsec(2)
137 :
138 0 : real(dp), allocatable :: kin(:),occ_tmp(:)
139 :
140 : ! *********************************************************************
141 :
142 0 : call timab(tim_slicewf,1,tsec)
143 :
144 0 : paw = gs_hamk%usepaw==1
145 :
146 : ! Set module variables
147 0 : l_prtvol = prtvol
148 0 : l_mpi_enreg => mpi_enreg
149 0 : l_gs_hamk => gs_hamk
150 :
151 0 : cprjdim = xg_nonlop%cprjdim
152 :
153 : !Variables
154 0 : blockdim=mpi_enreg%nproc_band*mpi_enreg%bandpp
155 0 : nband_cprj=nband/mpi_enreg%nproc_band
156 :
157 : !Depends on istwfk
158 0 : if ( gs_hamk%istwf_k > 1 ) then ! Real only
159 : ! SPACE_CR mean that we have complex numbers but no re*im terms only re*re
160 : ! and im*im so that a vector of complex is consider as a long vector of real
161 : ! therefore the number of data is (2*npw*nspinor)*nband
162 : ! This space is completely equivalent to SPACE_R but will correctly set and
163 : ! get the array data into the xgBlock
164 0 : space = SPACE_CR
165 : else ! complex
166 0 : space = SPACE_C
167 : end if
168 0 : space_cprj = xg_nonlop%space_cprj
169 :
170 : !For kinetic part of the Hamiltonian
171 0 : ABI_MALLOC(kin,(gs_hamk%npw_fft_k))
172 0 : call build_kin(kin,gs_hamk%kinpw_k,gs_hamk%npw_fft_k)
173 0 : call xgBlock_map_1d(xg_kin,kin,SPACE_R,gs_hamk%npw_fft_k)
174 :
175 : ! Local variables for slice
176 0 : me_g0 = -1
177 0 : me_g0_fft = -1
178 0 : if (space==SPACE_CR) then
179 0 : me_g0 = 0
180 0 : me_g0_fft = 0
181 0 : if (gs_hamk%istwf_k == 2) then
182 0 : if (l_mpi_enreg%me_g0 == 1) me_g0 = 1
183 0 : if (l_mpi_enreg%me_g0_fft == 1) me_g0_fft = 1
184 : end if
185 : end if
186 0 : call xgBlock_map(xgx0,cg,space,npw*nspinor,nband,l_mpi_enreg%comm_band,me_g0=me_g0)
187 :
188 0 : call xgBlock_map_1d(xgeigen,eig,SPACE_R,nband)
189 :
190 0 : call xgBlock_map_1d(xgresidu,resid,SPACE_R,nband)
191 :
192 0 : call xgBlock_map_1d(xgenl,enl_out,SPACE_R,nband)
193 :
194 : ! Occupancies in chebyshev are used for convergence criteria only
195 0 : if (dtset%nbdbuf==-101.and.nspinor==1.and.dtset%nsppol==1) then
196 0 : ABI_MALLOC(occ_tmp,(nband))
197 0 : occ_tmp(:) = half*occ(:)
198 0 : call xgBlock_map_1d(xgocc,occ_tmp,SPACE_R,nband,gpu_option=dtset%gpu_option)
199 : else
200 0 : call xgBlock_map_1d(xgocc,occ,SPACE_R,nband,gpu_option=dtset%gpu_option)
201 : end if
202 :
203 : !call xg_cprj_copy(cprj_cwavef_bands,cprj_contiguous,space_cprj,nband_cprj,cprj_xgx0,&
204 : ! & xg_nonlop,l_mpi_enreg%comm_band,CPRJ_ALLOC)
205 0 : call xg_init(cprj_xgx0,space_cprj,xg_nonlop%cprjdim,nband_cprj*nspinor,comm=l_mpi_enreg%comm_band)
206 :
207 : call slice_init(slice,nband,npw*nspinor,cprjdim,dtset%tolwfr_diago,dtset%ecut, &
208 : & mpi_enreg%bandpp, dtset%nline, dtset%nbdbuf, space,space_cprj,1, &
209 : & l_mpi_enreg%comm_band,me_g0,paw,&
210 : & dtset%nslice,0.d0,dtset%paral_slice,0,&
211 0 : & xg_nonlop,me_g0_fft)
212 :
213 : ! Run slice
214 0 : call slice_run_cprj(slice,xgx0,cprj_xgx0%self,xg_getghc,xg_kin,xgeigen,xgocc,xgresidu,xgenl,nspinor)
215 :
216 0 : if (allocated(occ_tmp)) then
217 0 : ABI_FREE(occ_tmp)
218 : end if
219 0 : ABI_FREE(kin)
220 :
221 : ! call xg_cprj_copy(cprj_cwavef_bands,cprj_contiguous,space_cprj,nband_cprj,cprj_xgx0,&
222 : ! & xg_nonlop,l_mpi_enreg%comm_band,CPRJ_FREE)
223 0 : call xg_free(cprj_xgx0)
224 :
225 : ! Free slice
226 0 : call slice_free(slice)
227 :
228 0 : call timab(tim_slicewf,2,tsec)
229 :
230 : DBG_EXIT("COLL")
231 :
232 0 : end subroutine slicewf_cprj
233 : !!***
234 :
235 : !!****f* m_slice/xg_getghc
236 : !! NAME
237 : !! xg_getghc
238 : !!
239 : !! FUNCTION
240 : !! This routine computes H|C> and possibly S|C> for a given wave function C.
241 : !! It acts as a driver for getghc, taken into account parallelism, multithreading, etc.
242 : !!
243 : !! SIDE EFFECTS
244 : !! X <type(xgBlock_t)>= memory block containing |C>
245 : !! AX <type(xgBlock_t)>= memory block containing H|C>
246 : !!
247 : !! PARENTS
248 : !!
249 : !! CHILDREN
250 : !! xgBlock_getSize,xgBlock_reverseMap,xgBlock_scale,xgBlock_copy
251 : !! multithreaded_getghc
252 : !!
253 : !! SOURCE
254 : !
255 0 : subroutine xg_getghc(X,AX)
256 :
257 : use iso_c_binding
258 :
259 : !Arguments ------------------------------------
260 : type(xgBlock_t), intent(inout) :: X
261 : type(xgBlock_t), intent(inout) :: AX
262 :
263 : !Local variables-------------------------------
264 : !scalars
265 : integer :: blockdim
266 : integer :: spacedim
267 : integer,parameter :: sij_opt=0,cpopt=-1,type_calc=1 ! Compute local part only
268 : ! integer :: iatom,iband,ispinor,cprj_index,cprj_rows,cprj_cols,ncpgr,nlmn
269 : real(dp) :: eval
270 0 : type(pawcprj_type) :: cprj_dum(l_gs_hamk%natom,1)
271 : !arrays
272 0 : real(dp), pointer :: cg(:,:)
273 0 : real(dp), pointer :: ghc(:,:)
274 : real(dp) :: gsc(1,1),gvnlxc(1,1)
275 :
276 : ! *********************************************************************
277 :
278 0 : call xgBlock_getSize(X,spacedim,blockdim)
279 0 : call xgBlock_check(X,AX)
280 :
281 0 : call xgBlock_reverseMap(X,cg,rows=1,cols=spacedim*blockdim)
282 0 : call xgBlock_reverseMap(AX,ghc,rows=1,cols=spacedim*blockdim)
283 :
284 : ! Apply only local part of the Hamiltonian
285 : call multithreaded_getghc(cpopt,cg,cprj_dum,ghc,gsc,&
286 0 : l_gs_hamk,gvnlxc,eval,l_mpi_enreg,blockdim,l_prtvol,sij_opt,l_tim_getghc,type_calc)
287 :
288 0 : end subroutine xg_getghc
289 : !!***
290 :
291 0 : subroutine build_kin(kin,kinpw,npw)
292 :
293 : integer,intent(in) :: npw
294 : real(dp),intent(in) :: kinpw(:)
295 : real(dp),intent(out) :: kin(:)
296 :
297 : integer :: ipw
298 :
299 : !$omp parallel do schedule(static), shared(kin,kinpw)
300 0 : do ipw=1,npw
301 0 : if(kinpw(ipw)>huge(0.0_dp)*1.d-11) then
302 0 : kin(ipw)=0.d0
303 : else
304 0 : kin(ipw) = kinpw(ipw)
305 : end if
306 : end do
307 :
308 0 : end subroutine build_kin
309 :
310 : end module m_slicewf_cprj
311 : !!***
|