Branch data Line data Source code
1 : : !!****f* ABINIT/m_lobpcgwf_cprj
2 : : !! NAME
3 : : !! m_lobpcgwf_cprj
4 : : !!
5 : : !! FUNCTION
6 : : !! This routine updates the whole wave functions at a given k-point,
7 : : !! using the lobpcg method
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) 1998-2026 ABINIT group (LB)
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 : : !! SOURCE
20 : :
21 : : #if defined HAVE_CONFIG_H
22 : : #include "config.h"
23 : : #endif
24 : :
25 : : #include "abi_common.h"
26 : :
27 : : module m_lobpcgwf_cprj
28 : :
29 : : use, intrinsic :: iso_c_binding
30 : : use defs_basis
31 : : use m_abicore
32 : : use m_lobpcg
33 : : use m_errors
34 : : use m_time
35 : : use m_xomp
36 : : use m_fstrings
37 : : use m_xg
38 : : use m_xg_nonlop
39 : : use m_xgTransposer
40 : : use m_lobpcg2_cprj
41 : : use m_dtset
42 : :
43 : : use defs_abitypes, only : mpi_type
44 : : use m_hamiltonian, only : gs_hamiltonian_type
45 : : use m_getghc, only : multithreaded_getghc
46 : : use m_pawcprj, only : pawcprj_type
47 : :
48 : : implicit none
49 : :
50 : : private
51 : :
52 : : integer, parameter :: l_tim_getghc=5
53 : :
54 : : ! For use in getghc_gsc1
55 : : integer, save :: l_prtvol
56 : : type(mpi_type),pointer,save :: l_mpi_enreg
57 : : type(gs_hamiltonian_type),pointer,save :: l_gs_hamk
58 : :
59 : : public :: lobpcgwf2_cprj
60 : :
61 : : contains
62 : : !!***
63 : :
64 : 4036 : subroutine lobpcgwf2_cprj(cg,dtset,eig,occ,enl_out,gs_hamk,isppol,ikpt,inonsc,istep,kinpw,mpi_enreg,&
65 : 4036 : & nband,npw,nspinor,prtvol,resid,nbdbuf,xg_nonlop)
66 : :
67 : :
68 : : use m_cgtools, only : dotprod_g
69 : :
70 : : !Arguments ------------------------------------
71 : : integer,intent(in) :: nband,npw,prtvol,nspinor
72 : : integer,intent(in) :: isppol,ikpt,inonsc,istep,nbdbuf
73 : : type(gs_hamiltonian_type),target,intent(inout) :: gs_hamk
74 : : type(dataset_type) ,intent(in ) :: dtset
75 : : type(mpi_type) ,target,intent(in) :: mpi_enreg
76 : : real(dp) ,target,intent(inout) :: cg(2,nspinor*nband*npw)
77 : : real(dp) ,intent(in ) :: kinpw(npw)
78 : : real(dp) ,target,intent( out) :: resid(nband)
79 : : real(dp) ,intent( out) :: enl_out(nband)
80 : : real(dp) ,target,intent( out) :: eig(nband)
81 : : real(dp) ,target,intent(in ) :: occ(nband)
82 : : type(xg_nonlop_t) ,target,intent(in ) :: xg_nonlop
83 : :
84 : : !Local variables-------------------------------
85 : :
86 : : type(xgBlock_t) :: xgx0
87 : : !type(xgBlock_t) :: cprj_xgx0
88 : : type(xg_t) :: cprj_xgx0
89 : : type(xgBlock_t) :: xgeigen
90 : : type(xgBlock_t) :: xgresidu
91 : : type(xgBlock_t) :: xgocc
92 : : type(xgBlock_t) :: xgenl
93 : : type(xgBlock_t) :: xg_precond,xg_kin
94 : 4036 : type(lobpcg_t) :: lobpcg
95 : :
96 : : integer :: space, space_cprj, blockdim, cprjdim, nband_cprj
97 : : integer :: me_g0, me_g0_fft
98 : :
99 : : integer, parameter :: tim_lobpcgwf2 = 2030
100 : : real(dp) :: tsec(2)
101 : :
102 : 4036 : real(dp), allocatable :: occ_tmp(:)
103 : : ! Important things for NC
104 : 4036 : real(dp), allocatable :: pcon(:),kin(:)
105 : : ! real(dp), allocatable :: cprj_contiguous(:,:)
106 : :
107 : : ! *********************************************************************
108 : :
109 : 4036 : call timab(tim_lobpcgwf2,1,tsec)
110 : :
111 : : ! Set module variables
112 : 4036 : l_prtvol = prtvol
113 : 4036 : l_mpi_enreg => mpi_enreg
114 : 4036 : l_gs_hamk => gs_hamk
115 : :
116 : 4036 : cprjdim = xg_nonlop%cprjdim
117 : :
118 : : !Variables
119 : 4036 : blockdim=nband/dtset%nblock_lobpcg
120 [ - + ]: 4036 : if (blockdim/=mpi_enreg%nproc_band*mpi_enreg%bandpp) then
121 : 0 : ABI_ERROR('blockdim is not consistent with nproc_band and bandpp')
122 : : end if
123 : 4036 : nband_cprj=nband/mpi_enreg%nproc_band
124 : :
125 : : !Depends on istwfk
126 [ + + ]: 4036 : if ( gs_hamk%istwf_k > 1 ) then ! Real only
127 : : ! SPACE_CR mean that we have complex numbers but no re*im terms only re*re
128 : : ! and im*im so that a vector of complex is consider as a long vector of real
129 : : ! therefore the number of data is (2*npw*nspinor)*nband
130 : : ! This space is completely equivalent to SPACE_R but will correctly set and
131 : : ! get the array data into the xgBlock
132 : 2124 : space = SPACE_CR
133 : : else ! complex
134 : 1912 : space = SPACE_C
135 : : end if
136 : 4036 : space_cprj = xg_nonlop%space_cprj
137 : :
138 : : !For kinetic part of the Hamiltonian
139 [ - + + - : 12108 : ABI_MALLOC(kin,(npw))
+ - + - -
+ - + -
+ ]
140 : 4036 : call build_kin(kin,kinpw,npw)
141 : 4036 : call xgBlock_map_1d(xg_kin,kin,SPACE_R,npw)
142 : :
143 : : !For preconditionning
144 [ - + + - : 8072 : ABI_MALLOC(pcon,(npw))
- + - + -
+ ]
145 : 4036 : call build_pcon(pcon,kinpw,npw)
146 : :
147 : : ! Local variables for lobpcg
148 : 4036 : me_g0 = -1
149 : 4036 : me_g0_fft = -1
150 [ + + ]: 4036 : if (space==SPACE_CR) then
151 : 2124 : me_g0 = 0
152 : 2124 : me_g0_fft = 0
153 [ + + ]: 2124 : if (gs_hamk%istwf_k == 2) then
154 [ + + ]: 339 : if (l_mpi_enreg%me_g0 == 1) me_g0 = 1
155 [ + - ]: 339 : if (l_mpi_enreg%me_g0_fft == 1) me_g0_fft = 1
156 : : end if
157 : : end if
158 : 4036 : call xgBlock_map(xgx0,cg,space,npw*nspinor,nband,l_mpi_enreg%comm_band,me_g0=me_g0)
159 : :
160 : 4036 : call xgBlock_map_1d(xg_precond,pcon,SPACE_R,npw)
161 : :
162 : 4036 : call xgBlock_map_1d(xgeigen,eig,SPACE_R,nband)
163 : :
164 : 4036 : call xgBlock_map_1d(xgresidu,resid,SPACE_R,nband)
165 : :
166 : 4036 : call xgBlock_map_1d(xgenl,enl_out,SPACE_R,nband)
167 : :
168 : 4036 : call xg_init(cprj_xgx0,space_cprj,xg_nonlop%cprjdim,nband_cprj*nspinor,comm=l_mpi_enreg%comm_band)
169 : :
170 : : ! Occupancies in LOBPCG are used for convergence criteria only
171 [ - + - - : 4036 : if (dtset%nbdbuf==-101.and.nspinor==1.and.dtset%nsppol==1) then
- - ]
172 [ # # # # : 0 : ABI_MALLOC(occ_tmp,(nband))
# # # # #
# # # #
# ]
173 [ # # ]: 0 : occ_tmp(:) = half*occ(:)
174 : 0 : call xgBlock_map_1d(xgocc,occ_tmp,SPACE_R,nband,gpu_option=dtset%gpu_option)
175 : : else
176 : 4036 : call xgBlock_map_1d(xgocc,occ,SPACE_R,nband,gpu_option=dtset%gpu_option)
177 : : end if
178 : :
179 : : call lobpcg_init(lobpcg,mpi_enreg%bandpp,nband,npw*nspinor,cprjdim,blockdim,dtset%tolwfr_diago,dtset%nline,&
180 : : space,space_cprj,l_mpi_enreg%comm_band,dtset%paral_kgb,xg_nonlop,l_mpi_enreg%comm_spinorfft,l_mpi_enreg%comm_band,&
181 : 4036 : me_g0,me_g0_fft)
182 : :
183 : : ! Run lobpcg
184 : : call lobpcg_run_cprj(lobpcg,xgx0,cprj_xgx0%self,xg_getghc,xg_kin,xg_precond,xgeigen,xgocc,xgresidu,xgenl,&
185 : 4036 : prtvol,nspinor,isppol,ikpt,inonsc,istep,nbdbuf)
186 : :
187 [ - + ]: 4036 : if (allocated(occ_tmp)) then
188 : 0 : ABI_FREE(occ_tmp)
189 : : end if
190 : : ! Free preconditionning since not needed anymore
191 [ - + ]: 4036 : ABI_FREE(pcon)
192 [ - + ]: 4036 : ABI_FREE(kin)
193 : :
194 : 4036 : call xg_free(cprj_xgx0)
195 : :
196 : : ! Free lobpcg
197 : 4036 : call lobpcg_free(lobpcg)
198 : :
199 : 4036 : call timab(tim_lobpcgwf2,2,tsec)
200 : :
201 : : DBG_EXIT("COLL")
202 : :
203 [ - + - + : 8072 : end subroutine lobpcgwf2_cprj
+ - + - +
- + - - +
- + - + -
+ - + - +
- + ]
204 : : !!***
205 : :
206 : : !!****f* m_lobpcg/xg_getghc
207 : : !! NAME
208 : : !! xg_getghc
209 : : !!
210 : : !! FUNCTION
211 : : !! This routine computes H|C> and possibly S|C> for a given wave function C.
212 : : !! It acts as a driver for getghc, taken into account parallelism, multithreading, etc.
213 : : !!
214 : : !! SIDE EFFECTS
215 : : !! X <type(xgBlock_t)>= memory block containing |C>
216 : : !! AX <type(xgBlock_t)>= memory block containing H|C>
217 : : !!
218 : : !! SOURCE
219 : : !
220 : 75096 : subroutine xg_getghc(X,AX)
221 : :
222 : : !Arguments ------------------------------------
223 : : type(xgBlock_t), intent(inout) :: X
224 : : type(xgBlock_t), intent(inout) :: AX
225 : :
226 : : !Local variables-------------------------------
227 : : !scalars
228 : : integer :: blockdim
229 : : integer :: spacedim
230 : : integer,parameter :: sij_opt=0,cpopt=-1,type_calc=1 ! Compute local part only
231 : : ! integer :: iatom,iband,ispinor,cprj_index,cprj_rows,cprj_cols,ncpgr,nlmn
232 : : real(dp) :: eval
233 [ + + + + : 1051344 : type(pawcprj_type) :: cprj_dum(l_gs_hamk%natom,1)
+ + + + +
- + - ]
234 : : !arrays
235 : 75096 : real(dp), pointer :: cg(:,:)
236 : 75096 : real(dp), pointer :: ghc(:,:)
237 : : real(dp) :: gsc(1,1),gvnlxc(1,1)
238 : :
239 : : ! *********************************************************************
240 : :
241 : 75096 : call xgBlock_getSize(X,spacedim,blockdim)
242 : 75096 : call xgBlock_check(X,AX)
243 : :
244 : 75096 : call xgBlock_reverseMap(X,cg,rows=1,cols=spacedim*blockdim)
245 : 75096 : call xgBlock_reverseMap(AX,ghc,rows=1,cols=spacedim*blockdim)
246 : :
247 : : ! Apply only local part of the Hamiltonian
248 : : call multithreaded_getghc(cpopt,cg,cprj_dum,ghc,gsc,&
249 : 75096 : l_gs_hamk,gvnlxc,eval,l_mpi_enreg,blockdim,l_prtvol,sij_opt,l_tim_getghc,type_calc)
250 : :
251 : 150192 : end subroutine xg_getghc
252 : : !!***
253 : :
254 [ - + - + ]: 4036 : subroutine build_pcon(pcon,kinpw,npw)
255 : :
256 : : integer,intent(in) :: npw
257 : : real(dp),intent(in) :: kinpw(:)
258 : : real(dp),intent(out) :: pcon(:)
259 : :
260 : : integer :: ipw
261 : :
262 : : !$omp parallel do schedule(static), shared(pcon,kinpw)
263 [ + + ]: 269445 : do ipw=1,npw
264 [ + + ]: 269445 : if(kinpw(ipw)>huge(0.0_dp)*1.d-11) then
265 : 5848 : pcon(ipw)=0.d0
266 : : else
267 : : pcon(ipw) = (27+kinpw(ipw)*(18+kinpw(ipw)*(12+8*kinpw(ipw)))) &
268 : 259561 : & / (27+kinpw(ipw)*(18+kinpw(ipw)*(12+8*kinpw(ipw))) + 16*kinpw(ipw)**4)
269 : : end if
270 : : end do
271 : :
272 : 4036 : end subroutine build_pcon
273 : :
274 [ - + - + ]: 4036 : subroutine build_kin(kin,kinpw,npw)
275 : :
276 : : integer,intent(in) :: npw
277 : : real(dp),intent(in) :: kinpw(:)
278 : : real(dp),intent(out) :: kin(:)
279 : :
280 : : integer :: ipw
281 : :
282 : : !$omp parallel do schedule(static), shared(kin,kinpw)
283 [ + + ]: 269445 : do ipw=1,npw
284 [ + + ]: 269445 : if(kinpw(ipw)>huge(0.0_dp)*1.d-11) then
285 : 5848 : kin(ipw)=0.d0
286 : : else
287 : 259561 : kin(ipw) = kinpw(ipw)
288 : : end if
289 : : end do
290 : :
291 : 4036 : end subroutine build_kin
292 : :
293 : : end module m_lobpcgwf_cprj
294 : : !!***
|