Line data Source code
1 :
2 : #if defined HAVE_CONFIG_H
3 : #include "config.h"
4 : #endif
5 :
6 : #include "abi_common.h"
7 :
8 : module m_lobpcg2_cprj
9 :
10 : use defs_basis
11 : use m_xg
12 : use m_xg_nonlop
13 : use m_xg_ortho_RR
14 : use m_xgTransposer
15 : use m_xgScalapack
16 : use defs_basis
17 : use m_abicore
18 : use m_errors
19 : use m_xomp
20 : #ifdef HAVE_OPENMP
21 : use omp_lib
22 : #endif
23 :
24 : use m_xmpi
25 : use m_time, only : timab
26 :
27 : implicit none
28 :
29 : private
30 :
31 : integer, parameter :: tim_init = 2040
32 : integer, parameter :: tim_free = 2041
33 : integer, parameter :: tim_cprj = 2043
34 : integer, parameter :: tim_ortho = 2044
35 : integer, parameter :: tim_transpose = 2039
36 : integer, parameter :: tim_maxres = 2046
37 : integer, parameter :: tim_ax_k = 2048
38 : integer, parameter :: tim_ax_v = 2049
39 : integer, parameter :: tim_ax_nl = 2050
40 : integer, parameter :: tim_pcond = 2047
41 :
42 : integer, parameter :: tim_Bortho_X = 2031
43 : integer, parameter :: tim_Bortho_XW = 2032
44 : integer, parameter :: tim_Bortho_XWP = 2033
45 : integer, parameter :: tim_Bortho_Xall = 2034
46 : integer, parameter :: tim_RR_X = 2035
47 : integer, parameter :: tim_RR_XW = 2036
48 : integer, parameter :: tim_RR_XWP = 2037
49 : integer, parameter :: tim_RR_Xall = 2038
50 :
51 : integer, parameter :: tim_copy = 2042
52 : integer, parameter :: tim_nbdbuf = 2045
53 :
54 : integer, parameter :: tim_enl = 2051
55 :
56 : type, public :: lobpcg_t
57 : logical :: is_nested ! For OpenMP nested region
58 : integer :: spacedim ! Space dimension for one vector (WFs)
59 : integer :: space ! Space type for one vector
60 : integer :: space_cprj ! Space type for one projector
61 : integer :: cprjdim ! Space dimension for one vector (cprj)
62 : integer :: neigenpairs ! Number of eigen values/vectors we want
63 : integer :: nblock ! Number of block in the space of dim spacedim
64 : integer :: blockdim ! Number of vectors in one block
65 : integer :: blockdim_cprj ! Number of vectors in one block (for cprj array)
66 : integer :: nline ! Number of line to perform
67 : integer :: spacecom ! Communicator for MPI
68 : integer :: paral_kgb ! paral_kgb formalism or not
69 : integer :: comm_rows ! communicator for rows
70 : integer :: comm_cols ! communicator for cols
71 : integer :: me_g0
72 : integer :: me_g0_fft
73 : double precision :: tolerance ! Tolerance on the residu to stop the minimization
74 : integer :: prtvol
75 : type(xg_nonlop_t) :: xg_nonlop ! contains data for nonlocal operations
76 : type(xgBlock_t) :: AllX0 ! Block of initial and final solution.
77 : type(xgBlock_t) :: AllcprjX0 ! Block of initial and final solution.
78 : type(xgBlock_t) :: X0
79 : type(xgBlock_t) :: cprjX0
80 : ! Dim is (cplx*spacedim,neigenpair)
81 : !double precision, allocatable :: eig(:) ! Actual eigen values
82 :
83 : ! Some denomination here
84 : ! X, W, P are the shifts where their block vectors starts.
85 : ! X is the current block we are solving
86 : ! W is the residu of the pencil A-lambda*B ie W=A*X-lambdaB*X
87 : ! P correspond to X_{iline} - X_{iline-1}
88 : ! if prefixed by A (AX, AW, AP) it means the result of A*X (A*W, A*P ! respectively)
89 : ! Idem for B (BX, BW, BP) which is the result of B*X (B*W, B*P)
90 : ! An extend to this is AXWP which is the vector [AX,AW,AP]
91 : ! and BXWP which is [BX,BW,BP] columnwise
92 : ! Now we only allocate the triple XWP matrix and each individual X, W and P
93 : ! Example : XWP=[x1,x2,x3,w1,w2,w3,p1,p2,p3] X points to the indice of x1-1, W points to w1-1 and
94 : ! P to p1-1
95 : type(xg_t) :: XWP
96 : type(xg_t) :: AXWP
97 : type(xg_t) :: cprjXWP
98 :
99 : type(xg_t) :: cprj_work
100 : type(xg_t) :: cprj_work2
101 :
102 : type(xgBlock_t) :: XColsRows
103 : type(xgBlock_t) :: AXColsRows
104 :
105 : type(xgTransposer_t) :: xgTransposerX
106 : type(xgTransposer_t) :: xgTransposerAX
107 :
108 : type(xgBlock_t) :: WColsRows
109 : type(xgBlock_t) :: AWColsRows
110 :
111 : type(xgTransposer_t) :: xgTransposerW
112 : type(xgTransposer_t) :: xgTransposerAW
113 :
114 : type(xgBlock_t) :: X ! Shift to apply to start reading the X values
115 : type(xgBlock_t) :: W ! Shift to apply to start reading the W values
116 : type(xgBlock_t) :: P ! Shift to apply to start reading the P values
117 : type(xgBlock_t) :: XW ! Shift to apply to start reading the P values
118 : type(xgBlock_t) :: WP ! Shift to apply to start reading the P values
119 :
120 : type(xgBlock_t) :: AX ! Shift to apply to start reading the X values
121 : type(xgBlock_t) :: AW ! Shift to apply to start reading the W values
122 : type(xgBlock_t) :: AP ! Shift to apply to start reading the P values
123 : type(xgBlock_t) :: AXW ! Shift to apply to start reading the P values
124 : type(xgBlock_t) :: AWP ! Shift to apply to start reading the P values
125 :
126 : type(xgBlock_t) :: cprjX ! Shift to apply to start reading the X values
127 : type(xgBlock_t) :: cprjW ! Shift to apply to start reading the W values
128 : type(xgBlock_t) :: cprjP ! Shift to apply to start reading the P values
129 : type(xgBlock_t) :: cprjXW ! Shift to apply to start reading the P values
130 : type(xgBlock_t) :: cprjWP ! Shift to apply to start reading the P values
131 :
132 : type(xg_t) :: AllAX0
133 :
134 : type(xgBlock_t) :: AllX0ColsRows
135 : type(xgBlock_t) :: AllAX0ColsRows
136 :
137 : type(xgTransposer_t) :: xgTransposerAllX0
138 : type(xgTransposer_t) :: xgTransposerAllAX0
139 :
140 : end type lobpcg_t
141 :
142 : public :: lobpcg_init
143 : public :: lobpcg_memInfo
144 : public :: lobpcg_run_cprj
145 : public :: lobpcg_free
146 :
147 : contains
148 :
149 :
150 4036 : subroutine lobpcg_init(lobpcg, bandpp, neigenpairs, spacedim, cprjdim, blockdim, tolerance, nline, &
151 : & space, space_cprj, spacecom, paral_kgb, xg_nonlop, comm_rows, comm_cols, me_g0, me_g0_fft)
152 :
153 : type(lobpcg_t) , intent(inout) :: lobpcg
154 : type(xg_nonlop_t), intent(in ) :: xg_nonlop
155 : integer , intent(in ) :: neigenpairs
156 : integer , intent(in ) :: spacedim
157 : integer , intent(in ) :: cprjdim
158 : integer , intent(in ) :: blockdim
159 : integer , intent(in ) :: bandpp
160 : double precision , intent(in ) :: tolerance
161 : integer , intent(in ) :: nline
162 : integer , intent(in ) :: comm_rows,comm_cols
163 : integer , intent(in ) :: space
164 : integer , intent(in ) :: space_cprj
165 : integer , intent(in ) :: spacecom
166 : integer , intent(in ) :: paral_kgb
167 : integer , intent(in ) :: me_g0
168 : integer , intent(in ) :: me_g0_fft
169 : double precision :: tsec(2)
170 :
171 4036 : call timab(tim_init,1,tsec)
172 4036 : lobpcg%neigenpairs = neigenpairs
173 4036 : lobpcg%spacedim = spacedim
174 4036 : lobpcg%space = space
175 4036 : lobpcg%space_cprj = space_cprj
176 4036 : lobpcg%cprjdim = cprjdim
177 4036 : lobpcg%nblock = neigenpairs / blockdim
178 4036 : lobpcg%blockdim = blockdim
179 4036 : lobpcg%blockdim_cprj = bandpp*xg_nonlop%nspinor
180 4036 : if (tolerance > 0.0) then
181 0 : lobpcg%tolerance = tolerance
182 : else
183 4036 : lobpcg%tolerance = 1e-20
184 : end if
185 4036 : lobpcg%nline = nline
186 4036 : lobpcg%spacecom = spacecom
187 4036 : lobpcg%paral_kgb = paral_kgb
188 4036 : lobpcg%comm_rows = comm_rows
189 4036 : lobpcg%comm_cols = comm_cols
190 4036 : lobpcg%xg_nonlop = xg_nonlop
191 4036 : lobpcg%me_g0 = me_g0
192 4036 : lobpcg%me_g0_fft = me_g0_fft
193 :
194 4036 : call lobpcg_allocateAll(lobpcg)
195 4036 : call timab(tim_init,2,tsec)
196 :
197 4036 : end subroutine lobpcg_init
198 :
199 :
200 4036 : subroutine lobpcg_allocateAll(lobpcg)
201 :
202 : type(lobpcg_t) , intent(inout) :: lobpcg
203 : integer :: spacedim
204 : integer :: cprjdim
205 : integer :: blockdim
206 : integer :: blockdim_cprj
207 :
208 4036 : spacedim = lobpcg%spacedim
209 4036 : blockdim = lobpcg%blockdim
210 :
211 4036 : cprjdim = lobpcg%cprjdim
212 4036 : blockdim_cprj = lobpcg%blockdim_cprj
213 :
214 4036 : call lobpcg_free(lobpcg) ! Make sure everything is not allocated and
215 : ! pointer point to null()
216 :
217 4036 : call xg_init(lobpcg%XWP,lobpcg%space,spacedim,3*blockdim,lobpcg%spacecom,me_g0=lobpcg%me_g0)
218 4036 : call xg_setBlock(lobpcg%XWP,lobpcg%X,spacedim,blockdim)
219 4036 : call xg_setBlock(lobpcg%XWP,lobpcg%W,spacedim,blockdim,fcol=blockdim+1)
220 4036 : call xg_setBlock(lobpcg%XWP,lobpcg%P,spacedim,blockdim,fcol=2*blockdim+1)
221 4036 : call xg_setBlock(lobpcg%XWP,lobpcg%XW,spacedim,2*blockdim)
222 4036 : call xg_setBlock(lobpcg%XWP,lobpcg%WP,spacedim,2*blockdim,fcol=blockdim+1)
223 :
224 4036 : call xg_init(lobpcg%AXWP,lobpcg%space,spacedim,3*blockdim,lobpcg%spacecom,me_g0=lobpcg%me_g0)
225 4036 : call xg_setBlock(lobpcg%AXWP,lobpcg%AX,spacedim,blockdim)
226 4036 : call xg_setBlock(lobpcg%AXWP,lobpcg%AW,spacedim,blockdim,fcol=blockdim+1)
227 4036 : call xg_setBlock(lobpcg%AXWP,lobpcg%AP,spacedim,blockdim,fcol=2*blockdim+1)
228 4036 : call xg_setBlock(lobpcg%AXWP,lobpcg%AXW,spacedim,2*blockdim)
229 4036 : call xg_setBlock(lobpcg%AXWP,lobpcg%AWP,spacedim,2*blockdim,fcol=blockdim+1)
230 :
231 4036 : call xg_init(lobpcg%cprjXWP,lobpcg%space_cprj,cprjdim,3*blockdim_cprj,lobpcg%spacecom)
232 4036 : call xg_setBlock(lobpcg%cprjXWP,lobpcg%cprjX, cprjdim, blockdim_cprj)
233 4036 : call xg_setBlock(lobpcg%cprjXWP,lobpcg%cprjW, cprjdim, blockdim_cprj,fcol= blockdim_cprj+1)
234 4036 : call xg_setBlock(lobpcg%cprjXWP,lobpcg%cprjP, cprjdim, blockdim_cprj,fcol= 2*blockdim_cprj+1)
235 4036 : call xg_setBlock(lobpcg%cprjXWP,lobpcg%cprjXW,cprjdim,2*blockdim_cprj)
236 4036 : call xg_setBlock(lobpcg%cprjXWP,lobpcg%cprjWP,cprjdim,2*blockdim_cprj,fcol= blockdim_cprj+1)
237 :
238 4036 : call xg_init(lobpcg%cprj_work ,lobpcg%space_cprj,cprjdim,blockdim_cprj,lobpcg%spacecom)
239 4036 : call xg_init(lobpcg%cprj_work2,lobpcg%space_cprj,cprjdim,blockdim_cprj,lobpcg%spacecom)
240 :
241 4036 : if ( lobpcg%nblock /= 1 ) then
242 4004 : call xg_init(lobpcg%AllAX0,lobpcg%space,spacedim,lobpcg%neigenpairs,lobpcg%spacecom,me_g0=lobpcg%me_g0)
243 : else
244 32 : lobpcg%AllAX0%self = lobpcg%AX
245 : end if
246 :
247 4036 : end subroutine lobpcg_allocateAll
248 :
249 :
250 0 : function lobpcg_memInfo(neigenpairs, spacedim, blockdim, space) result(arraymem)
251 :
252 : integer , intent(in ) :: neigenpairs
253 : integer , intent(in ) :: spacedim
254 : integer , intent(in ) :: blockdim
255 : integer , intent(in ) :: space
256 : double precision :: memXWP
257 : double precision :: memAXWP
258 : double precision :: memBXWP
259 : double precision :: memAllBX0
260 : double precision :: memAllAX0
261 : double precision :: memeigenvalues3N
262 : double precision :: membufferOrtho
263 : double precision :: membufferBOrtho
264 : double precision :: memsubA
265 : double precision :: memsubB
266 : double precision :: memsubBtmp
267 : double precision :: memvec
268 : double precision :: memRR
269 : double precision :: maxmemTmp
270 : double precision :: cplx
271 : integer :: nblock
272 : double precision :: arraymem(2)
273 :
274 0 : cplx = 1 ; if ( space == SPACE_C ) cplx = 2
275 0 : nblock = neigenpairs/blockdim
276 :
277 : ! Permanent in lobpcg
278 0 : memXWP = cplx* kind(1.d0) * spacedim * 3*blockdim
279 0 : memAXWP = cplx* kind(1.d0) * spacedim * 3*blockdim
280 0 : memBXWP = cplx* kind(1.d0) * spacedim * 3*blockdim
281 0 : if ( nblock > 1 ) then
282 0 : memAllAX0 = cplx * kind(1.d0) * spacedim * 3*blockdim
283 0 : memAllBX0 = cplx * kind(1.d0) * spacedim * 3*blockdim
284 0 : membufferOrtho = cplx * kind(1.d0) * blockdim * (nblock-1) * blockdim
285 : else
286 : memAllAX0 = 0
287 : memAllBX0 = 0
288 : membufferOrtho = 0
289 : endif
290 0 : memeigenvalues3N = kind(1.d0) * 3*blockdim
291 :
292 : ! Temporary arrays
293 0 : membufferBOrtho = cplx * kind(1.d0) * 2*blockdim * 2*blockdim ! For the moment being, only Bortho with X or WP at the same time
294 0 : memsubA = cplx * kind(1.d0) * 3*blockdim * 3*blockdim
295 0 : memsubB = cplx * kind(1.d0) * 3*blockdim * 3*blockdim
296 0 : memsubBtmp = cplx * kind(1.d0) * spacedim * blockdim
297 0 : memvec = cplx * kind(1.d0) * 3*blockdim * blockdim
298 0 : memRR = max(memsubA+memsubB+memvec,memsubBtmp+memvec)
299 :
300 0 : maxmemTmp = max( membufferBOrtho,memRR,membufferOrtho )
301 :
302 0 : arraymem(1) = memXWP+memAXWP+memBXWP+memAllAX0+memAllBX0+memeigenvalues3N
303 0 : arraymem(2) = maxmemTmp
304 :
305 0 : end function lobpcg_memInfo
306 :
307 :
308 12108 : subroutine lobpcg_run_cprj(lobpcg, X0, cprjX0, getAX, kin, pcond, eigen, occ, residu, enl, prtvol, nspinor, &
309 : isppol, ikpt, inonsc, istep, nbdbuf)
310 :
311 : type(lobpcg_t) , intent(inout) :: lobpcg
312 : type(xgBlock_t), intent(inout) :: X0 ! Full initial vectors
313 : type(xgBlock_t), intent(inout) :: cprjX0 ! Full initial cprj
314 : type(xgBlock_t), intent(inout) :: eigen ! Full initial eigen values
315 : type(xgBlock_t), intent(inout) :: occ
316 : type(xgBlock_t), intent(inout) :: residu
317 : type(xgBlock_t), intent(inout) :: enl
318 : type(xgBlock_t), intent(in ) :: kin
319 : type(xgBlock_t), intent(in ) :: pcond
320 : integer , intent(in ) :: prtvol
321 : integer , intent(in ) :: nspinor
322 : integer , intent(in ) :: isppol,ikpt,inonsc,istep,nbdbuf
323 :
324 : type(xg_t) :: eigenvalues3N ! eigen values for Rayleight-Ritz
325 : type(xg_t) :: residu_eff
326 : type(xgBlock_t) :: eigenvaluesN ! eigen values for Rayleight-Ritz
327 : type(xgBlock_t) :: eigenvalues2N ! eigen values for Rayleight-Ritz
328 : logical :: skip,compute_residu
329 : integer :: blockdim, blockdim3, blockdim2, blockdim_cprj
330 : integer :: spacedim
331 : integer :: iblock, nblock
332 : integer :: iline, nline
333 : integer :: rows_tmp, cols_tmp, nband_eff, iband_min, iband_max
334 : integer,parameter :: gpu_option=ABI_GPU_DISABLED
335 : type(xgBlock_t) :: eigenBlock !
336 : type(xgBlock_t) :: residuBlock,occBlock
337 : type(xg_t):: cprj_work_all
338 : double precision :: maxResidu, minResidu, dummy
339 : double precision :: dlamch,tolerance
340 : integer :: ierr = 0
341 : integer :: nrestart
342 : double precision :: tsec(2)
343 : character(len=500) :: msg
344 :
345 : interface
346 : subroutine getAX(X,AX)
347 : use m_xg, only : xgBlock_t
348 : type(xgBlock_t), intent(inout) :: X
349 : type(xgBlock_t), intent(inout) :: AX
350 : end subroutine getAX
351 : end interface
352 :
353 4036 : lobpcg%prtvol = prtvol
354 :
355 8072 : tolerance=2*dlamch('E')
356 :
357 4036 : blockdim = lobpcg%blockdim
358 4036 : blockdim2 = 2*blockdim
359 4036 : blockdim3 = 3*blockdim
360 4036 : blockdim_cprj = lobpcg%blockdim_cprj
361 4036 : spacedim = lobpcg%spacedim
362 :
363 4036 : nblock = lobpcg%nblock
364 4036 : nline = lobpcg%nline
365 :
366 4036 : if (nbdbuf>0) then
367 4036 : nband_eff = lobpcg%neigenpairs - nbdbuf
368 : else
369 0 : nband_eff = lobpcg%neigenpairs
370 : end if
371 :
372 4036 : call xgBlock_getSize(eigen,rows_tmp, cols_tmp)
373 4036 : if ( rows_tmp /= lobpcg%neigenpairs .and. cols_tmp /= 1 ) then
374 0 : ABI_ERROR("Error eigen size")
375 : endif
376 4036 : call xgBlock_getSize(X0,rows_tmp, cols_tmp)
377 4036 : if ( rows_tmp /= lobpcg%spacedim ) then
378 0 : ABI_ERROR("Error X0 spacedim")
379 : endif
380 4036 : if ( cols_tmp /= lobpcg%neigenpairs ) then
381 0 : ABI_ERROR("Error X0 npairs")
382 : endif
383 :
384 4036 : if (isppol==1.and.ikpt==1.and.inonsc==1.and.istep==1) then
385 42 : write(msg,'(a,es16.6)') ' lobpcg%tolerance(tolwfr_diago)=',lobpcg%tolerance
386 42 : call wrtout(std_out,msg,'COLL')
387 : end if
388 :
389 4036 : call xg_init(eigenvalues3N,SPACE_R,blockdim3,1)
390 4036 : call xg_setBlock(eigenvalues3N,eigenvaluesN,blockdim,1)
391 4036 : call xg_setBlock(eigenvalues3N,eigenvalues2N,blockdim2,1)
392 :
393 4036 : call xgBlock_reshape(eigen,blockdim,nblock)
394 4036 : call xgBlock_reshape(residu,blockdim,nblock)
395 4036 : call xgBlock_reshape(occ,blockdim,nblock)
396 :
397 4036 : lobpcg%AllX0 = X0
398 4036 : lobpcg%AllcprjX0 = cprjX0
399 :
400 4036 : call xg_init(residu_eff,SPACE_R,blockdim,1,gpu_option=ABI_GPU_DISABLED)
401 :
402 4036 : if ( lobpcg%paral_kgb == 1 ) then
403 2684 : call timab(tim_transpose,1,tsec)
404 : call xgTransposer_constructor(lobpcg%xgTransposerX,lobpcg%X,lobpcg%XColsRows,nspinor,&
405 2684 : STATE_LINALG,TRANS_ALL2ALL,lobpcg%comm_rows,lobpcg%comm_cols,0,0,lobpcg%me_g0_fft)
406 : call xgTransposer_copyConstructor(lobpcg%xgTransposerAX,lobpcg%xgTransposerX,&
407 2684 : lobpcg%AX,lobpcg%AXColsRows,STATE_LINALG)
408 : call xgTransposer_copyConstructor(lobpcg%xgTransposerW,lobpcg%xgTransposerX,&
409 2684 : lobpcg%W,lobpcg%WColsRows,STATE_LINALG)
410 : call xgTransposer_copyConstructor(lobpcg%xgTransposerAW,lobpcg%xgTransposerX,&
411 2684 : lobpcg%AW,lobpcg%AWColsRows,STATE_LINALG)
412 2684 : call timab(tim_transpose,2,tsec)
413 : else
414 1352 : call xgBlock_setBlock(lobpcg%X, lobpcg%XColsRows, spacedim, blockdim)
415 1352 : call xgBlock_setBlock(lobpcg%AX, lobpcg%AXColsRows, spacedim, blockdim)
416 1352 : call xgBlock_setBlock(lobpcg%W, lobpcg%WColsRows, spacedim, blockdim)
417 1352 : call xgBlock_setBlock(lobpcg%AW, lobpcg%AWColsRows, spacedim, blockdim)
418 : end if
419 :
420 : !! Start big loop over blocks
421 20628 : do iblock = 1, nblock
422 16592 : nrestart = 0
423 :
424 16592 : call lobpcg_getX0(lobpcg,iblock)
425 16592 : call xgBlock_setBlock(residu,residuBlock,blockdim,1,fcol=iblock)
426 16592 : call xgBlock_setBlock(occ, occBlock, blockdim,1,fcol=iblock)
427 :
428 16592 : call timab(tim_cprj,1,tsec)
429 16592 : call xg_nonlop_getcprj(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,lobpcg%cprj_work%self)
430 16592 : call timab(tim_cprj,2,tsec)
431 :
432 16592 : if ( iblock > 1 ) then
433 12556 : call lobpcg_setPreviousX0(lobpcg,iblock)
434 : ! Orthogonalize current iblock X block With Respect To previous Blocks in B-basis
435 12556 : call lobpcg_orthoXwrtBlocks(lobpcg,lobpcg%X,lobpcg%cprjX,iblock,lobpcg%cprj_work%self)
436 : end if
437 :
438 16592 : if (lobpcg%paral_kgb == 1) then
439 11184 : call timab(tim_transpose,1,tsec)
440 11184 : call xgTransposer_transpose(lobpcg%xgTransposerX,STATE_COLSROWS)
441 11184 : lobpcg%xgTransposerAX%state=STATE_COLSROWS
442 11184 : call timab(tim_transpose,2,tsec)
443 : end if
444 :
445 : ! Initialize some quantitites (AX)
446 16592 : call timab(tim_ax_v,1,tsec)
447 16592 : call getAX(lobpcg%XColsRows,lobpcg%AXColsRows)
448 16592 : call xgBlock_zero_im_g0(lobpcg%AXColsRows)
449 16592 : call timab(tim_ax_v,2,tsec)
450 16592 : if (lobpcg%paral_kgb == 1) then
451 11184 : call timab(tim_transpose,1,tsec)
452 11184 : lobpcg%xgTransposerX%state=STATE_LINALG
453 11184 : call xgTransposer_transpose(lobpcg%xgTransposerAX,STATE_LINALG)
454 11184 : call timab(tim_transpose,2,tsec)
455 : end if
456 :
457 16592 : call timab(tim_ax_k,1,tsec)
458 16592 : call xgBlock_add_diag(lobpcg%X,kin,nspinor,lobpcg%AX)
459 16592 : call timab(tim_ax_k,2,tsec)
460 :
461 : ! B-orthonormalize X, BX and AX
462 16592 : call xg_Borthonormalize_cprj(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,ierr,tim_Bortho_X,gpu_option,AX=lobpcg%AX)
463 :
464 : ! Do first RR on X to get the first eigen values
465 : call xg_RayleighRitz_cprj(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,lobpcg%AX,eigenvaluesN,ierr,&
466 16592 : & lobpcg%prtvol,tim_RR_X,gpu_option,add_Anl=.True.)
467 :
468 16592 : compute_residu = .true.
469 :
470 75096 : do iline = 1, nline
471 :
472 67717 : if ( ierr /= 0 ) then
473 : !ABI_COMMENT("Consider using more bands and nbdbuf if necessary.")
474 0 : ierr = 0
475 : end if
476 :
477 : ! Compute AX-Lambda*BX
478 67717 : call timab(tim_copy,1,tsec)
479 67717 : call xgBlock_copy(lobpcg%AX,lobpcg%W)
480 67717 : call timab(tim_copy,2,tsec)
481 : ! Add the non-local part: (A_nl - Lambda*B)X
482 67717 : call timab(tim_ax_nl,1,tsec)
483 67717 : if (lobpcg%xg_nonlop%paw) then
484 : call xg_nonlop_getHmeSX(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,lobpcg%W,eigenvaluesN,&
485 55920 : lobpcg%cprj_work%self,lobpcg%cprj_work2%self)
486 : else
487 : call xg_nonlop_getHX(lobpcg%xg_nonlop,lobpcg%W,lobpcg%cprjX,&
488 11797 : lobpcg%cprj_work%self,lobpcg%cprj_work2%self)
489 11797 : call xgBlock_yxmax(lobpcg%W,eigenvaluesN,lobpcg%X)
490 : end if
491 67717 : call timab(tim_ax_nl,2,tsec)
492 :
493 : ! Compute residu norm here !
494 67717 : call timab(tim_maxres,1,tsec)
495 67717 : call xgBlock_colwiseNorm2(lobpcg%W,residuBlock)
496 67717 : call timab(tim_maxres,2,tsec)
497 :
498 : ! Apply preconditioner
499 67717 : call timab(tim_pcond,1,tsec)
500 67717 : call xgBlock_apply_diag(lobpcg%W,pcond,nspinor)
501 67717 : call timab(tim_pcond,2,tsec)
502 :
503 67717 : call timab(tim_nbdbuf,1,tsec)
504 67717 : if (nbdbuf>=0) then
505 : ! There is a transfer from GPU to CPU in this copy
506 67717 : call xgBlock_copy(residuBlock,residu_eff%self)
507 67717 : iband_min = 1 + blockdim*(iblock-1)
508 67717 : iband_max = blockdim*iblock
509 67717 : if (iband_max<=nband_eff) then ! all bands of this block are below nband_eff
510 57269 : call xgBlock_minmax(residu_eff%self,minResidu,maxResidu)
511 10448 : else if (iband_min<=nband_eff) then ! some bands of this block are below nband_eff
512 3120 : call xgBlock_minmax(residu_eff%self,minResidu,maxResidu,row_bound=(nband_eff-iband_min+1))
513 : else ! all bands of this block are above nband_eff
514 7328 : minResidu = 0.0
515 7328 : maxResidu = 0.0
516 : end if
517 0 : else if (nbdbuf==-101) then
518 0 : call xgBlock_minmax(residuBlock,minResidu,dummy) ! Get minimum of true residuals
519 : ! Compute effective residuals : res_eff = res * occ
520 0 : call xgBlock_apply_diag(residuBlock,occBlock,1,Y=residu_eff%self)
521 0 : call xgBlock_minmax(residu_eff%self,dummy,maxResidu) ! Get maximum of effective residuals
522 : else
523 0 : ABI_ERROR('Bad value of nbdbuf')
524 : end if
525 67717 : call timab(tim_nbdbuf,2,tsec)
526 67717 : if ( maxResidu < lobpcg%tolerance ) then
527 : compute_residu = .false.
528 : exit
529 : end if
530 :
531 58504 : call timab(tim_cprj,1,tsec)
532 58504 : call xg_nonlop_getcprj(lobpcg%xg_nonlop,lobpcg%W,lobpcg%cprjW,lobpcg%cprj_work%self)
533 58504 : call timab(tim_cprj,2,tsec)
534 :
535 : ! Orthonormalize with respect to previous blocks
536 58504 : if ( iblock > 1 ) then
537 32398 : call lobpcg_orthoXwrtBlocks(lobpcg,lobpcg%W,lobpcg%cprjW,iblock,lobpcg%cprj_work%self)
538 : end if
539 :
540 58504 : if (lobpcg%paral_kgb == 1) then
541 37406 : call timab(tim_transpose,1,tsec)
542 37406 : call xgTransposer_transpose(lobpcg%xgTransposerW,STATE_COLSROWS)
543 37406 : lobpcg%xgTransposerAW%state=STATE_COLSROWS
544 37406 : call timab(tim_transpose,2,tsec)
545 : end if
546 : ! Apply A and B on W
547 58504 : call timab(tim_ax_v,1,tsec)
548 58504 : call getAX(lobpcg%WColsRows,lobpcg%AWColsRows)
549 58504 : call xgBlock_zero_im_g0(lobpcg%AWColsRows)
550 58504 : call timab(tim_ax_v,2,tsec)
551 58504 : if (lobpcg%paral_kgb == 1) then
552 37406 : call timab(tim_transpose,1,tsec)
553 37406 : lobpcg%xgTransposerW%state=STATE_LINALG
554 37406 : call xgTransposer_transpose(lobpcg%xgTransposerAW,STATE_LINALG)
555 37406 : call timab(tim_transpose,2,tsec)
556 : end if
557 :
558 58504 : call timab(tim_ax_k,1,tsec)
559 58504 : call xgBlock_add_diag(lobpcg%W,kin,nspinor,lobpcg%AW)
560 58504 : call timab(tim_ax_k,2,tsec)
561 :
562 : ! DO RR in the correct subspace
563 : ! if residu starts to be too small, there is an accumulation error in
564 : ! P with values such as 1e-29 that make the eigenvectors diverge
565 65883 : if ( iline == 1 .or. minResidu < 1e-27) then
566 : ! Do RR on XW to get the eigen vectors
567 : call xg_Borthonormalize_cprj(lobpcg%xg_nonlop,lobpcg%XW,lobpcg%cprjXW,&
568 8938 : & ierr,tim_Bortho_XW,gpu_option,AX=lobpcg%AXW,blockdim_cprj=blockdim_cprj)
569 8938 : call xgBlock_zero(lobpcg%P)
570 8938 : call xgBlock_zero(lobpcg%AP)
571 8938 : call xgBlock_zero(lobpcg%cprjP)
572 8938 : if ( ierr /= 0 ) then
573 0 : ABI_COMMENT("B-orthonormalization (XW) did not work.")
574 : end if
575 : call xg_RayleighRitz_cprj(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,lobpcg%AX,eigenvaluesN,ierr,&
576 : & lobpcg%prtvol,tim_RR_XW,gpu_option,tolerance=tolerance,&
577 : & XW=lobpcg%XW,W=lobpcg%W,cprjXW=lobpcg%cprjXW,cprjW=lobpcg%cprjW,AW=lobpcg%AW,&
578 : & P=lobpcg%P,cprjP=lobpcg%cprjP,AP=lobpcg%AP,WP=lobpcg%WP,cprjWP=lobpcg%cprjWP,&
579 8938 : & AWP=lobpcg%AWP,blockdim_cprj=blockdim_cprj,add_Anl=.True.)
580 8938 : if ( ierr /= 0 ) then
581 0 : ABI_WARNING("RayleighRitz (XW) did not work, but continue anyway.")
582 : exit
583 : end if
584 : else
585 : ! B-orthonormalize P, BP
586 : call xg_Borthonormalize_cprj(lobpcg%xg_nonlop,lobpcg%XWP%self,lobpcg%cprjXWP%self,&
587 49566 : & ierr,tim_Bortho_XWP,gpu_option,AX=lobpcg%AXWP%self,blockdim_cprj=blockdim_cprj)
588 : ! Do RR on XWP to get the eigen vectors
589 49566 : if ( ierr == 0 ) then
590 : call xg_RayleighRitz_cprj(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,lobpcg%AX,eigenvaluesN,ierr,&
591 : & lobpcg%prtvol,tim_RR_XWP,gpu_option,tolerance=tolerance,&
592 : & XW=lobpcg%XW,W=lobpcg%W,cprjXW=lobpcg%cprjXW,cprjW=lobpcg%cprjW,AW=lobpcg%AW,&
593 : & P=lobpcg%P,cprjP=lobpcg%cprjP,AP=lobpcg%AP,WP=lobpcg%WP,cprjWP=lobpcg%cprjWP,&
594 49566 : & AWP=lobpcg%AWP,XWP=lobpcg%XWP%self,cprjXWP=lobpcg%cprjXWP%self,blockdim_cprj=blockdim_cprj,add_Anl=.True.)
595 49566 : if ( ierr /= 0 ) then
596 0 : ABI_WARNING("RayleighRitz (XWP) did not work, but continue anyway.")
597 : exit
598 : end if
599 : else
600 0 : ABI_COMMENT("B-orthonormalization (XWP) did not work, try on XW.")
601 : call xg_Borthonormalize_cprj(lobpcg%xg_nonlop,lobpcg%XW,lobpcg%cprjXW,&
602 0 : & ierr,tim_Bortho_XW,gpu_option,AX=lobpcg%AXW,blockdim_cprj=blockdim_cprj)
603 0 : if ( ierr /= 0 ) then
604 0 : ABI_COMMENT("B-orthonormalization (XW) did not work.")
605 : end if
606 0 : call xgBlock_zero(lobpcg%P)
607 0 : call xgBlock_zero(lobpcg%AP)
608 0 : call xgBlock_zero(lobpcg%cprjP)
609 0 : nrestart = nrestart + 1
610 : call xg_RayleighRitz_cprj(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,lobpcg%AX,eigenvaluesN,ierr,&
611 : & lobpcg%prtvol,tim_RR_XW,gpu_option,tolerance=tolerance,&
612 : & XW=lobpcg%XW,W=lobpcg%W,cprjXW=lobpcg%cprjXW,cprjW=lobpcg%cprjW,AW=lobpcg%AW,&
613 : & P=lobpcg%P,cprjP=lobpcg%cprjP,AP=lobpcg%AP,WP=lobpcg%WP,cprjWP=lobpcg%cprjWP,&
614 0 : & AWP=lobpcg%AWP,blockdim_cprj=blockdim_cprj,add_Anl=.True.)
615 0 : if ( ierr /= 0 ) then
616 0 : ABI_WARNING("RayleighRitz (XW) did not work, but continue anyway.")
617 : exit
618 : end if
619 : end if
620 : end if
621 :
622 : end do
623 :
624 16592 : if ( compute_residu ) then
625 : ! Recompute AX-Lambda*BX for the last time
626 7379 : call timab(tim_copy,1,tsec)
627 7379 : call xgBlock_copy(lobpcg%AX,lobpcg%W)
628 7379 : call timab(tim_copy,2,tsec)
629 7379 : call timab(tim_ax_nl,1,tsec)
630 7379 : if (lobpcg%xg_nonlop%paw) then
631 : call xg_nonlop_getHmeSX(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,lobpcg%W,eigenvaluesN,&
632 6305 : lobpcg%cprj_work%self,lobpcg%cprj_work2%self)
633 : else
634 : call xg_nonlop_getHX(lobpcg%xg_nonlop,lobpcg%W,lobpcg%cprjX,&
635 1074 : lobpcg%cprj_work%self,lobpcg%cprj_work2%self)
636 1074 : call xgBlock_yxmax(lobpcg%W,eigenvaluesN,lobpcg%X)
637 : end if
638 7379 : call timab(tim_ax_nl,2,tsec)
639 : ! Recompute residu norm here !
640 7379 : call timab(tim_maxres,1,tsec)
641 7379 : call xgBlock_colwiseNorm2(lobpcg%W,residuBlock)
642 7379 : call timab(tim_maxres,2,tsec)
643 : ! Apply preconditioner
644 7379 : call timab(tim_pcond,1,tsec)
645 7379 : call xgBlock_apply_diag(lobpcg%W,pcond,nspinor)
646 7379 : call timab(tim_pcond,2,tsec)
647 :
648 7379 : call timab(tim_nbdbuf,1,tsec)
649 7379 : if (nbdbuf>=0) then
650 7379 : call xgBlock_copy(residuBlock,residu_eff%self)
651 7379 : iband_min = 1 + blockdim*(iblock-1)
652 7379 : iband_max = blockdim*iblock
653 7379 : if (iband_max<=nband_eff) then ! all bands of this block are below nband_eff
654 6871 : call xgBlock_minmax(residu_eff%self,minResidu,maxResidu)
655 508 : else if (iband_min<=nband_eff) then ! some bands of this block are below nband_eff
656 508 : call xgBlock_minmax(residu_eff%self,minResidu,maxResidu,row_bound=(nband_eff-iband_min+1))
657 : else ! all bands of this block are above nband_eff
658 0 : minResidu = 0.0
659 0 : maxResidu = 0.0
660 : end if
661 0 : else if (nbdbuf==-101) then
662 0 : call xgBlock_minmax(residuBlock,minResidu,dummy) ! Get minimum of true residuals
663 : ! Compute effective residuals : res_eff = res * occ
664 0 : call xgBlock_apply_diag(residuBlock,occBlock,1,Y=residu_eff%self)
665 0 : call xgBlock_minmax(residu_eff%self,dummy,maxResidu) ! Get maximum of effective residuals
666 : else
667 0 : ABI_ERROR('Bad value of nbdbuf')
668 : end if
669 7379 : call timab(tim_nbdbuf,2,tsec)
670 : end if
671 :
672 16592 : if (prtvol==5.and.xmpi_comm_rank(lobpcg%spacecom)==0) then
673 0 : write(msg,'(6(a,i4),2(a,es16.6))') 'lobpcg | istep=',istep,'| isppol=',isppol,'| ikpt=',ikpt,&
674 0 : & '| inonsc=',inonsc,'| iblock=',iblock,'| nline_done=',iline-1,'| minRes=',minResidu,'| maxRes=',maxResidu
675 0 : call wrtout(std_out,msg,'PERS')
676 : end if
677 :
678 : ! Save eigenvalues
679 16592 : call timab(tim_copy,1,tsec)
680 16592 : call xgBlock_setBlock(eigen,eigenBlock,blockdim,1,fcol=iblock)
681 16592 : call xgBlock_copy(eigenvaluesN,eigenBlock)
682 16592 : call timab(tim_copy,2,tsec)
683 :
684 : ! Save new X in X0
685 16592 : call lobpcg_setX0(lobpcg,iblock)
686 :
687 : ! Copy previous BX into BX0 for previous block
688 20628 : if ( nblock > 1 ) then
689 16560 : call lobpcg_transferAX_BX(lobpcg,iblock)
690 : end if
691 :
692 : end do !! End iblock loop
693 :
694 4036 : call xgBlock_reshape(eigen,blockdim*nblock,1)
695 4036 : call xgBlock_reshape(residu,blockdim*nblock,1)
696 4036 : call xgBlock_reshape(occ,blockdim*nblock,1)
697 :
698 4036 : call xg_free(eigenvalues3N)
699 4036 : call xg_free(residu_eff)
700 :
701 4036 : skip = .false.
702 4036 : if ( ierr /= 0 ) then
703 0 : ABI_COMMENT("Some errors happened, so H|Psi> and S|Psi> are computed before leaving")
704 0 : if ( lobpcg%paral_kgb == 1 ) then
705 : call xgTransposer_constructor(lobpcg%xgTransposerAllX0,lobpcg%AllX0,lobpcg%AllX0ColsRows,nspinor,&
706 0 : STATE_LINALG,TRANS_ALL2ALL,lobpcg%comm_rows,lobpcg%comm_cols,0,0,lobpcg%me_g0_fft)
707 : call xgTransposer_copyConstructor(lobpcg%xgTransposerAllAX0,lobpcg%xgTransposerAllX0,&
708 0 : lobpcg%AllAX0%self,lobpcg%AllAX0ColsRows,STATE_LINALG)
709 : else
710 0 : call xgBlock_setBlock(lobpcg%AllX0 , lobpcg%AllX0ColsRows , spacedim, lobpcg%neigenpairs)
711 0 : call xgBlock_setBlock(lobpcg%AllAX0%self, lobpcg%AllAX0ColsRows, spacedim, lobpcg%neigenpairs)
712 : end if
713 0 : if (lobpcg%paral_kgb == 1) then
714 0 : call timab(tim_transpose,1,tsec)
715 0 : call xgTransposer_transpose(lobpcg%xgTransposerAllX0,STATE_COLSROWS)
716 0 : lobpcg%xgTransposerAllAX0%state=STATE_COLSROWS
717 0 : call timab(tim_transpose,2,tsec)
718 : end if
719 0 : call timab(tim_ax_v,1,tsec)
720 0 : call getAX(lobpcg%AllX0ColsRows,lobpcg%AllAX0ColsRows)
721 0 : call xgBlock_zero_im_g0(lobpcg%AllAX0ColsRows)
722 0 : call timab(tim_ax_v,2,tsec)
723 0 : if (lobpcg%paral_kgb == 1) then
724 0 : call timab(tim_transpose,1,tsec)
725 0 : call xgTransposer_transpose(lobpcg%xgTransposerAllX0,STATE_LINALG)
726 0 : call xgTransposer_transpose(lobpcg%xgTransposerAllAX0,STATE_LINALG)
727 0 : call timab(tim_transpose,2,tsec)
728 : end if
729 :
730 0 : call timab(tim_ax_k,1,tsec)
731 0 : call xgBlock_add_diag(lobpcg%AllX0,kin,nspinor,lobpcg%AllAX0%self)
732 0 : call timab(tim_ax_k,2,tsec)
733 :
734 0 : call xgTransposer_free(lobpcg%xgTransposerAllX0)
735 0 : call xgTransposer_free(lobpcg%xgTransposerAllAX0)
736 : skip = .true.
737 : end if
738 :
739 : if (.not.skip) then
740 :
741 4036 : if ( nblock > 1 ) then
742 4004 : call timab(tim_cprj,1,tsec)
743 4004 : call xg_init(cprj_work_all,space(cprjX0),rows(cprjX0),cols(cprjX0),comm(cprjX0))
744 : ! cprj computation could be avoided, with MPI comm instead
745 4004 : call xg_nonlop_getcprj(lobpcg%xg_nonlop,X0,cprjX0,cprj_work_all%self)
746 4004 : call xg_free(cprj_work_all)
747 4004 : call timab(tim_cprj,2,tsec)
748 : call xg_Borthonormalize_cprj(lobpcg%xg_nonlop,X0,cprjX0,&
749 4004 : & ierr,tim_Bortho_Xall,gpu_option,AX=lobpcg%AllAX0%self)
750 : call xg_RayleighRitz_cprj(lobpcg%xg_nonlop,X0,cprjX0,lobpcg%AllAX0%self,eigen,ierr,&
751 4004 : & lobpcg%prtvol,tim_RR_Xall,gpu_option,add_Anl=.True.)
752 : end if
753 :
754 : end if
755 :
756 4036 : if ( lobpcg%paral_kgb == 1 ) then
757 2684 : call xgTransposer_free(lobpcg%xgTransposerX)
758 2684 : call xgTransposer_free(lobpcg%xgTransposerAX)
759 2684 : call xgTransposer_free(lobpcg%xgTransposerW)
760 2684 : call xgTransposer_free(lobpcg%xgTransposerAW)
761 : end if
762 :
763 4036 : if (.not.lobpcg%xg_nonlop%paw) then
764 816 : call timab(tim_enl,1,tsec)
765 816 : call xg_init(cprj_work_all,space(cprjX0),rows(cprjX0),cols(cprjX0),comm(cprjX0))
766 816 : call xg_nonlop_colwiseXHX(lobpcg%xg_nonlop,cprjX0,cprj_work_all%self,enl)
767 816 : call xg_free(cprj_work_all)
768 816 : call timab(tim_enl,2,tsec)
769 : end if
770 :
771 4036 : end subroutine lobpcg_run_cprj
772 :
773 16592 : subroutine lobpcg_getX0(lobpcg,iblock)
774 :
775 : type(lobpcg_t) , intent(inout) :: lobpcg
776 : integer , intent(in ) :: iblock
777 : type(xgBlock_t) :: Xtmp,cprjXtmp
778 : integer :: blockdim
779 : integer :: spacedim
780 : integer :: cprjdim
781 : integer :: blockdim_cprj
782 : double precision :: tsec(2)
783 :
784 16592 : call timab(tim_copy,1,tsec)
785 :
786 16592 : blockdim = lobpcg%blockdim
787 16592 : spacedim = lobpcg%spacedim
788 :
789 16592 : cprjdim = lobpcg%cprjdim
790 16592 : blockdim_cprj = lobpcg%blockdim_cprj
791 :
792 16592 : call xgBlock_setBlock(lobpcg%AllX0,Xtmp,spacedim,blockdim,fcol=(iblock-1)*blockdim+1)
793 16592 : call xgBlock_copy(Xtmp,lobpcg%X)
794 :
795 16592 : call xgBlock_setBlock(lobpcg%AllcprjX0,cprjXtmp,cprjdim,blockdim_cprj,fcol=(iblock-1)*blockdim_cprj+1)
796 16592 : call xgBlock_copy(cprjXtmp,lobpcg%cprjX)
797 :
798 16592 : call timab(tim_copy,2,tsec)
799 :
800 16592 : end subroutine lobpcg_getX0
801 :
802 :
803 12556 : subroutine lobpcg_setPreviousX0(lobpcg,iblock)
804 :
805 : type(lobpcg_t) , intent(inout) :: lobpcg
806 : integer , intent(in ) :: iblock
807 :
808 12556 : if (iblock<2) then
809 0 : ABI_ERROR("iblock<2")
810 : end if
811 12556 : call xgBlock_setBlock(lobpcg%AllX0 ,lobpcg%X0 ,lobpcg%spacedim,(iblock-1)*lobpcg%blockdim)
812 12556 : call xgBlock_setBlock(lobpcg%AllcprjX0,lobpcg%cprjX0,lobpcg%cprjdim ,(iblock-1)*lobpcg%blockdim_cprj)
813 12556 : end subroutine lobpcg_setPreviousX0
814 :
815 44954 : subroutine lobpcg_orthoXwrtBlocks(lobpcg,var,cprjvar,iblock,cprj_work)
816 :
817 : type(lobpcg_t) , intent(inout) :: lobpcg
818 : type(xgBlock_t), intent(inout) :: var
819 : type(xgBlock_t), intent(inout) :: cprjvar
820 : type(xgBlock_t), intent(inout) :: cprj_work
821 : integer , intent(in ) :: iblock
822 : integer :: previousBlock
823 : integer :: blockdim
824 : integer :: spacedim
825 : integer :: space_buf
826 : integer :: nspinor,cprjdim
827 : type(xg_t) :: buffer
828 : double precision :: tsec(2)
829 : type(xgBlock_t) :: cprjX0_spinor,cprj_work_spinor
830 :
831 44954 : call timab(tim_ortho,1,tsec)
832 :
833 44954 : if (iblock<2) then
834 0 : ABI_ERROR("iblock<2")
835 : end if
836 :
837 44954 : if (cols(cprjvar)/=cols(cprj_work)) then
838 0 : ABI_ERROR("cprjvar and cprj_work should have same number of columns")
839 : end if
840 44954 : blockdim = lobpcg%blockdim
841 44954 : spacedim = lobpcg%spacedim
842 44954 : previousBlock = (iblock-1)*lobpcg%blockdim
843 :
844 44954 : cprjdim = lobpcg%xg_nonlop%cprjdim
845 44954 : nspinor = lobpcg%xg_nonlop%nspinor
846 :
847 44954 : space_buf = space(var)
848 44954 : if (space(var)==SPACE_CR) then
849 20858 : space_buf = SPACE_R
850 : end if
851 44954 : call xg_init(buffer,space_buf,previousBlock,blockdim,lobpcg%spacecom)
852 :
853 : ! buffer = X0^T*X
854 44954 : call xgBlock_gemm('t','n',1.0d0,lobpcg%X0,var,0.d0,buffer%self,comm=lobpcg%spacecom)
855 :
856 : ! Add the nonlocal part if paw
857 44954 : if (lobpcg%xg_nonlop%paw) then
858 37654 : call xg_nonlop_getXSY(lobpcg%xg_nonlop,lobpcg%cprjX0,cprjvar,cprj_work,buffer%self)
859 : end if
860 :
861 : ! sum all process contribution
862 : ! X = - X0*(BX0^T*X) + X
863 44954 : call xgBlock_gemm('n','n',-1.0d0,lobpcg%X0,buffer%self,1.0d0,var)
864 :
865 44954 : call xgBlock_zero(cprj_work)
866 44954 : call xgBlock_reshape_spinor(cprj_work,cprj_work_spinor,nspinor,COLS2ROWS)
867 44954 : call xgBlock_reshape_spinor(lobpcg%cprjX0,cprjX0_spinor,nspinor,COLS2ROWS)
868 : call xgBlock_gemm_mpi_cyclic_permutation(cprjX0_spinor,buffer%self,cprj_work_spinor,&
869 44954 : & lobpcg%xg_nonlop%me_band,blocksize=lobpcg%blockdim_cprj/nspinor,comm=lobpcg%xg_nonlop%comm_band)
870 44954 : call xgBlock_saxpy(cprjvar,-1.0d0,cprj_work)
871 :
872 44954 : call xg_free(buffer)
873 :
874 44954 : call timab(tim_ortho,2,tsec)
875 :
876 44954 : end subroutine lobpcg_orthoXwrtBlocks
877 :
878 16592 : subroutine lobpcg_setX0(lobpcg,iblock)
879 :
880 : type(lobpcg_t) , intent(inout) :: lobpcg
881 : integer , intent(in ) :: iblock
882 : type(xgBlock_t) :: Xtmp,cprjXtmp
883 : integer :: blockdim
884 : integer :: spacedim
885 : integer :: cprjdim
886 : integer :: blockdim_cprj
887 : double precision :: tsec(2)
888 :
889 16592 : call timab(tim_copy,1,tsec)
890 16592 : blockdim = lobpcg%blockdim
891 16592 : spacedim = lobpcg%spacedim
892 :
893 16592 : cprjdim = lobpcg%cprjdim
894 16592 : blockdim_cprj = lobpcg%blockdim_cprj
895 :
896 : !X0(:,(iblock-1)*blockdim+1:iblock*blockdim) = lobpcg%XWP(:,lobpcg%X+1:lobpcg%X+blockdim)
897 16592 : call xgBlock_setBlock(lobpcg%AllX0,Xtmp,spacedim,blockdim,fcol=(iblock-1)*blockdim+1)
898 16592 : call xgBlock_copy(lobpcg%X,Xtmp)
899 :
900 16592 : call xgBlock_setBlock(lobpcg%AllcprjX0,cprjXtmp,cprjdim,blockdim_cprj,fcol=(iblock-1)*blockdim_cprj+1)
901 16592 : call xgBlock_copy(lobpcg%cprjX,cprjXtmp)
902 16592 : call timab(tim_copy,2,tsec)
903 :
904 16592 : end subroutine lobpcg_setX0
905 :
906 16560 : subroutine lobpcg_transferAX_BX(lobpcg,iblock)
907 :
908 : type(lobpcg_t), intent(inout) :: lobpcg
909 : integer , intent(in ) :: iblock
910 : type(xgBlock_t) :: CXtmp
911 : integer :: firstcol
912 : double precision :: tsec(2)
913 :
914 16560 : call timab(tim_copy,1,tsec)
915 :
916 16560 : if (iblock<1) then
917 0 : ABI_ERROR("iblock<1")
918 : end if
919 :
920 : ! iblock goes from 1 to nblock-1 included
921 16560 : firstcol = (iblock-1)*lobpcg%blockdim+1 ! Start of each block
922 :
923 : ! AX
924 16560 : call xg_setBlock(lobpcg%AllAX0,CXtmp,lobpcg%spacedim,lobpcg%blockdim,fcol=firstcol)
925 16560 : call xgBlock_copy(lobpcg%AX,CXtmp)
926 :
927 16560 : call timab(tim_copy,2,tsec)
928 :
929 16560 : end subroutine lobpcg_transferAX_BX
930 :
931 8072 : subroutine lobpcg_free(lobpcg)
932 :
933 : type(lobpcg_t), intent(inout) :: lobpcg
934 :
935 8072 : call xg_free(lobpcg%XWP)
936 8072 : call xg_free(lobpcg%AXWP)
937 8072 : call xg_free(lobpcg%cprjXWP)
938 8072 : call xg_free(lobpcg%cprj_work)
939 8072 : call xg_free(lobpcg%cprj_work2)
940 8072 : call xg_free(lobpcg%AllAX0)
941 :
942 8072 : end subroutine lobpcg_free
943 :
944 0 : end module m_lobpcg2_cprj
945 : !!***
|