Branch data Line data Source code
1 : : !!****m* ABINIT/m_gwls_GWlanczos
2 : : !! NAME
3 : : !! m_gwls_GWlanczos
4 : : !!
5 : : !! FUNCTION
6 : : !! .
7 : : !!
8 : : !! COPYRIGHT
9 : : !! Copyright (C) 2009-2026 ABINIT group (JLJ, BR, MC)
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 : : module m_gwls_GWlanczos
23 : : !----------------------------------------------------------------------------------------------------
24 : : ! This module implements the Lanczos scheme to band diagonalize an implicit operator.
25 : : !----------------------------------------------------------------------------------------------------
26 : : !local modules
27 : : use m_gwls_utility
28 : : use m_gwls_TimingLog
29 : : use m_gwls_wf
30 : : use m_gwls_hamiltonian
31 : : use m_gwls_lineqsolver
32 : : use m_gwls_polarisability
33 : : use m_gwls_QR_factorization
34 : :
35 : : !abinit modules
36 : : use defs_basis
37 : : use defs_wvltypes
38 : : use m_abicore
39 : : use m_xmpi
40 : : use m_pawang
41 : : use m_errors
42 : :
43 : : use m_io_tools, only : get_unit
44 : :
45 : : implicit none
46 : : save
47 : : private
48 : : !!***
49 : :
50 : : !!***
51 : : public :: block_lanczos_algorithm
52 : :
53 : : public :: diagonalize_lanczos_banded
54 : : public :: get_seeds
55 : : !!***
56 : : contains
57 : :
58 : :
59 : : !!****f* m_gwls_GWlanczos/get_seeds
60 : : !! NAME
61 : : !! get_seeds
62 : : !!
63 : : !! FUNCTION
64 : : !! .
65 : : !!
66 : : !! INPUTS
67 : : !!
68 : : !! OUTPUT
69 : : !!
70 : : !! SOURCE
71 : :
72 : 29 : subroutine get_seeds(first_seed, nseeds, seeds)
73 : : !----------------------------------------------------------------------------------------------------
74 : : !
75 : : ! This subroutine compute the seeds using the eigenstates of the Hamiltonian
76 : : !
77 : : !----------------------------------------------------------------------------------------------------
78 : : integer, intent(in) :: first_seed, nseeds
79 : : complex(dp), intent(out) :: seeds(npw_k,nseeds)
80 : :
81 : 29 : real(dp) , allocatable :: psik_out(:,:)
82 : 29 : real(dp) , allocatable :: psikb_e(:,:)
83 : 29 : real(dp) , allocatable :: psig_e(:,:)
84 : 29 : real(dp) , allocatable :: psikb_s(:,:)
85 : 29 : real(dp) , allocatable :: psig_s(:,:)
86 : :
87 : : ! local variables
88 : : integer :: n
89 : : integer :: i, j, nsblk
90 : : ! *************************************************************************
91 : :
92 : : ! Generate the seeds for the Lanczos algorithm
93 [ - + + - : 87 : ABI_MALLOC(psik_out,(2,npw_k))
+ - + - -
+ - + ]
94 [ - + + - : 87 : ABI_MALLOC(psikb_e,(2,npw_kb))
+ - + - -
+ - + ]
95 [ - + + - : 87 : ABI_MALLOC(psig_e,(2,npw_g))
+ - + - -
+ - + ]
96 [ - + + - : 58 : ABI_MALLOC(psikb_s,(2,npw_kb))
- + - + ]
97 [ - + + - : 58 : ABI_MALLOC(psig_s,(2,npw_g))
- + - + ]
98 : :
99 [ + + ]: 29 : nsblk = ceiling(1.0*nseeds/blocksize)
100 : :
101 [ + + ]: 68 : do i=1,nsblk
102 [ + + ]: 98 : do j=1,blocksize
103 [ + + + + ]: 22457 : psikb_e(:,(j-1)*npw_k+1:j*npw_k) = cg(:,(e-1)*npw_k+1:e*npw_k)
104 : : end do
105 : :
106 [ + + + + ]: 22398 : psig_e = zero
107 : 39 : call wf_block_distribute(psikb_e, psig_e,1) ! LA -> FFT
108 : :
109 [ + + ]: 98 : do j=1,blocksize
110 : 59 : n = (i-1)*blocksize + j-1 + first_seed
111 [ + + ]: 98 : if ((i-1)*blocksize + j <= nseeds) then
112 [ + + + + ]: 19318 : psikb_s(:,(j-1)*npw_k+1:j*npw_k) = cg(:,(n-1)*npw_k+1:n*npw_k)
113 : : else
114 [ + + + + ]: 3100 : psikb_s(:,(j-1)*npw_k+1:j*npw_k) = zero
115 : : end if
116 : : end do
117 : :
118 [ + + + + ]: 22398 : psig_s = zero
119 : 39 : call wf_block_distribute(psikb_s, psig_s,1) ! LA -> FFT
120 : :
121 : : ! Fourier transform valence wavefunction, to real space
122 : 39 : call g_to_r(psir1,psig_s)
123 : :
124 [ + + + + : 267501 : psir1(2,:,:,:) = -psir1(2,:,:,:)
+ + ]
125 : :
126 : 39 : call gr_to_g(psig_s,psir1,psig_e)
127 : :
128 : : ! return to LA configuration, in order to apply Coulomb potential
129 : 39 : call wf_block_distribute(psikb_s, psig_s,2) ! FFT -> LA
130 : :
131 [ + + ]: 127 : do j=1, blocksize
132 : 59 : n = (i-1)*blocksize + j
133 [ + + ]: 98 : if(n<=nseeds) then
134 [ + - - + : 19361 : psik_out = psikb_s(:,(j-1)*npw_k+1:j*npw_k)
- - + + +
+ ]
135 : 43 : call sqrt_vc_k(psik_out)
136 [ + + ]: 6468 : seeds(:,n) = cmplx_1*psik_out(1,:) + cmplx_i*psik_out(2,:)
137 : : end if
138 : : end do
139 : : end do
140 : :
141 [ - + ]: 29 : ABI_FREE(psik_out)
142 [ - + ]: 29 : ABI_FREE(psikb_e)
143 [ - + ]: 29 : ABI_FREE(psig_e)
144 [ - + ]: 29 : ABI_FREE(psikb_s)
145 [ - + ]: 29 : ABI_FREE(psig_s)
146 : :
147 : 29 : end subroutine get_seeds
148 : : !!***
149 : :
150 : : !!****f* m_gwls_GWlanczos/block_lanczos_algorithm
151 : : !! NAME
152 : : !! block_lanczos_algorithm
153 : : !!
154 : : !! FUNCTION
155 : : !! .
156 : : !!
157 : : !! INPUTS
158 : : !!
159 : : !! OUTPUT
160 : : !!
161 : : !! SOURCE
162 : :
163 [ - + - - : 173 : subroutine block_lanczos_algorithm(mpi_communicator,matrix_function,kmax,nseeds,Hsize,seeds,alpha,beta,Lbasis,X0,beta0,Qk)
- - ]
164 : : !----------------------------------------------------------------------------------------------------
165 : : !
166 : : ! This subroutine implements the Block Lanczos algorithm for an arbitrary, user-supplied function which
167 : : ! returns the action of the implicit matrix, which is assumed to be Hermitian.
168 : : !
169 : : !
170 : : !----------------------------------------------------------------------------------------------------
171 : :
172 : : !-----------------------------------------
173 : : ! interface with implicit matrix function
174 : : !-----------------------------------------
175 : : !********************************************************
176 : : !*** NOTE: ***
177 : : !*** ***
178 : : !*** There *appears* to be a bug in makemake; ***
179 : : !*** when the name of the function in the interface ***
180 : : !*** below contains the word "implicit", makemake ***
181 : : !*** yields an error. I suppose makemake simply ***
182 : : !*** parses for the word "implicit" without regards ***
183 : : !*** for the fact that it may simply be part of a ***
184 : : !*** naive developper's chosen name for the routine. ***
185 : : !*** Correspondingly, I change the name to ***
186 : : !*** "matrix_function" to avoid problems. ***
187 : : !*** ***
188 : : !*** Bruno Rousseau ***
189 : : !*** 08/13/2012 ***
190 : : !********************************************************
191 : : interface
192 : : subroutine matrix_function(v_out,v_in,l)
193 : :
194 : : use defs_basis
195 : :
196 : : integer, intent(in) :: l
197 : : complex(dp), intent(out) :: v_out(l)
198 : : complex(dp), intent(in) :: v_in(l)
199 : :
200 : : end subroutine matrix_function
201 : : end interface
202 : :
203 : : !------------------------------
204 : : ! input/output variables
205 : : !------------------------------
206 : :
207 : : integer, intent(in) :: mpi_communicator
208 : : integer, intent(in) :: kmax ! number of Lanczos blocks
209 : : integer, intent(in) :: nseeds ! size of each blocks
210 : : integer, intent(in) :: Hsize ! size of the Hilbert space in which the matrix lives
211 : :
212 : : complex(dp), intent(inout):: seeds(Hsize,nseeds) ! seed vectors for the algorithm
213 : : ! overwritten by X_{k+1} on output
214 : :
215 : : !logical, intent(in) :: ortho ! should the Lanczos vector be orthogonalized?
216 : :
217 : : complex(dp), intent(out) :: alpha(nseeds,nseeds,kmax) ! the alpha array from the Lanczos algorithm
218 : : complex(dp), intent(out) :: beta(nseeds,nseeds,kmax) ! the beta array from the Lanczos algorithm
219 : : complex(dp), intent(out) :: Lbasis(Hsize,nseeds*kmax) ! array containing the Lanczos basis
220 : :
221 : :
222 : : complex(dp), intent(in),optional :: X0(Hsize,nseeds)
223 : : complex(dp), intent(in),optional :: beta0(nseeds,nseeds)
224 : : complex(dp), intent(in),optional :: Qk(:,:) ! array containing vectors to which
225 : :
226 : : ! the basis must be orthonormalized
227 : :
228 : :
229 : :
230 : : !------------------------------
231 : : ! local variables
232 : : !------------------------------
233 : : integer :: k, seed1
234 : : integer :: dum(2), lk
235 : :
236 : 173 : complex(dp), allocatable :: xk(:,:), xkm1(:,:), rk(:,:)
237 : :
238 : : integer :: ntime, itime
239 : : real(dp) :: total_time1, total_time2
240 : : real(dp) :: time1, time2
241 : : integer :: ierr
242 : 173 : real(dp),allocatable :: list_time(:)
243 : :
244 : : ! *************************************************************************
245 : :
246 : 173 : call cpu_time(total_time1)
247 : :
248 : :
249 : 173 : ntime = 7
250 [ + - ]: 173 : ABI_MALLOC(list_time,(ntime))
251 [ + + ]: 1384 : list_time(:) = zero
252 : :
253 [ - + ]: 173 : if(present(Qk)) then
254 [ # # ]: 0 : dum = shape(Qk)
255 : 0 : lk = dum(2)
256 : : end if
257 : :
258 [ - + + - : 692 : ABI_MALLOC( xk, (Hsize,nseeds))
- + + - +
- + - - +
- + ]
259 [ - + + - : 519 : ABI_MALLOC( xkm1,(Hsize,nseeds))
- + + - -
+ - + ]
260 [ - + + - : 519 : ABI_MALLOC( rk ,(Hsize,nseeds))
- + + - -
+ + - ]
261 : :
262 : :
263 [ + + + + : 6165 : alpha = cmplx_0
+ + ]
264 [ + + + + : 6165 : beta = cmplx_0
+ + ]
265 : :
266 : : !------------------------------------------------
267 : : ! Orthonormalize the seeds
268 : : !------------------------------------------------
269 : : ! initialize the xk array with the seeds
270 [ + + + + ]: 35569 : xk(:,:) = seeds(:,:)
271 : :
272 : :
273 : : ! orthonormalize the block using the QR algorithm
274 : : ! xk is overwritten by Q, the array of orthonormal vectors
275 : :
276 : 173 : call extract_QR(mpi_communicator, Hsize,nseeds,xk)
277 : :
278 : : !------------------------------------------------
279 : : ! Loop on all blocks
280 : : !------------------------------------------------
281 : :
282 : :
283 [ + + ]: 2077 : do k = 1, kmax
284 : :
285 : 1904 : itime = 0
286 : :
287 : : ! tabulate basis, computed at previous step
288 [ + + + + ]: 384224 : Lbasis(:,nseeds*(k-1)+1:nseeds*k) = xk(:,:)
289 : :
290 : :
291 : 1904 : itime = itime+1
292 : 1904 : call cpu_time(time1)
293 : :
294 : : ! Initialize the residual array
295 [ + + ]: 3864 : do seed1 = 1, nseeds
296 : : ! If we are constructing the $\hat \epsilon(i\omega = 0)$ matrix (and the Lanczos basis at the same time),
297 : : ! note the index in which the Sternheimer solutions will be stored (for use in the projected Sternheimer section).
298 [ + + ]: 1960 : if(write_solution) index_solution = (k-1)*nseeds + seed1
299 : :
300 : 3864 : call matrix_function(rk(:,seed1),xk(:,seed1),Hsize)
301 : : end do
302 : :
303 : 1904 : call cpu_time(time2)
304 : 1904 : list_time(itime) = list_time(itime) + time2-time1
305 : :
306 : 1904 : itime = itime+1
307 : 1904 : call cpu_time(time1)
308 : : ! compute the alpha array, alpha = X^d.A.X
309 : :
310 : : call ZGEMM( 'C', & ! take Hermitian conjugate of first array
311 : : 'N', & ! leave second array as is
312 : : nseeds, & ! the number of rows of the matrix op( A )
313 : : nseeds, & ! the number of columns of the matrix op( B )
314 : : Hsize, & ! the number of columns of the matrix op( A ) == rows of matrix op( B )
315 : : cmplx_1, & ! alpha constant
316 : : xk, & ! matrix A
317 : : Hsize, & ! LDA
318 : : rk, & ! matrix B
319 : : Hsize, & ! LDB
320 : : cmplx_0, & ! beta constant
321 : : alpha(:,:,k), & ! matrix C
322 : 1904 : nseeds) ! LDC
323 : 1904 : call xmpi_sum(alpha(:,:,k),mpi_communicator,ierr) ! sum on all processors
324 : :
325 : :
326 : :
327 : 1904 : call cpu_time(time2)
328 : 1904 : list_time(itime) = list_time(itime) + time2-time1
329 : :
330 : 1904 : itime = itime+1
331 : 1904 : call cpu_time(time1)
332 : : ! update the residual array, rk = rk-X.alpha
333 : : call ZGEMM( 'N', & ! leave first array as is
334 : : 'N', & ! leave second array as is
335 : : Hsize, & ! the number of rows of the matrix op( A )
336 : : nseeds, & ! the number of columns of the matrix op( B )
337 : : nseeds, & ! the number of columns of the matrix op( A ) == rows of matrix op( B )
338 : : -cmplx_1, & ! alpha constant
339 : : xk, & ! matrix A
340 : : Hsize, & ! LDA
341 : : alpha(:,:,k), & ! matrix B
342 : : nseeds, & ! LDB
343 : : cmplx_1, & ! beta constant
344 : : rk, & ! matrix C
345 : 1904 : Hsize) ! LDC
346 : :
347 : 1904 : call cpu_time(time2)
348 : 1904 : list_time(itime) = list_time(itime) + time2-time1
349 : :
350 [ - + - - ]: 1904 : if (k .eq. 1 .and. present(X0) .and. present(beta0)) then
351 : : ! if k == 1, and X0,beta0 are present,
352 : : ! update the residual array, r1 = r1-X_{0}.beta^d_{0}
353 : : call ZGEMM( 'N', & ! leave first array as is
354 : : 'C', & ! Hermitian conjugate the second array
355 : : Hsize, & ! the number of rows of the matrix op( A )
356 : : nseeds, & ! the number of columns of the matrix op( B )
357 : : nseeds, & ! the number of columns of the matrix op( A ) == rows of matrix op( B )
358 : : -cmplx_1, & ! alpha constant
359 : : X0, & ! matrix A
360 : : Hsize, & ! LDA
361 : : beta0(:,:), & ! matrix B
362 : : nseeds, & ! LDB
363 : : cmplx_1, & ! beta constant
364 : : rk, & ! matrix C
365 : 0 : Hsize) ! LDC
366 : : end if
367 : :
368 : :
369 : 1904 : itime = itime+1
370 : 1904 : call cpu_time(time1)
371 [ + + ]: 1904 : if (k .gt. 1) then
372 : :
373 : : ! if k > 1, update the residual array, rk = rk-X_{k-1}.beta^d_{k-1}
374 : : call ZGEMM( 'N', & ! leave first array as is
375 : : 'C', & ! Hermitian conjugate the second array
376 : : Hsize, & ! the number of rows of the matrix op( A )
377 : : nseeds, & ! the number of columns of the matrix op( B )
378 : : nseeds, & ! the number of columns of the matrix op( A ) == rows of matrix op( B )
379 : : -cmplx_1, & ! alpha constant
380 : : xkm1, & ! matrix A
381 : : Hsize, & ! LDA
382 : : beta(:,:,k-1), & ! matrix B
383 : : nseeds, & ! LDB
384 : : cmplx_1, & ! beta constant
385 : : rk, & ! matrix C
386 : 1731 : Hsize) ! LDC
387 : :
388 : : end if
389 : 1904 : call cpu_time(time2)
390 : 1904 : list_time(itime) = list_time(itime) + time2-time1
391 : :
392 : : ! store xk for next iteration
393 [ + + + + ]: 384224 : xkm1(:,:) = xk(:,:)
394 : :
395 : :
396 : : ! Orthonormalize THE RESIDUAL to all previously calculated directions
397 : :
398 : 1904 : itime = itime+1
399 : 1904 : call cpu_time(time1)
400 : : !if ( ortho .and. (dtset%gwcalctyp/=1) ) then !This is a test to obtain the CPU time taken by the orthogonalizations.
401 : :
402 [ - + ]: 1904 : if(present(Qk)) then
403 : : ! Orthonormalize to all previously calculated directions, if
404 : : ! this is a restarted Lanczos step
405 [ # # # # : 0 : call orthogonalize(mpi_communicator, Hsize,lk,nseeds,Qk,rk)
# # # # #
# ]
406 : : end if
407 : :
408 : 1904 : call orthogonalize(mpi_communicator, Hsize,k*nseeds,nseeds,Lbasis(:,1:k*nseeds),rk)
409 : :
410 : : !end if
411 : 1904 : call cpu_time(time2)
412 : 1904 : list_time(itime) = list_time(itime) + time2-time1
413 : :
414 : :
415 : 1904 : itime = itime+1
416 : 1904 : call cpu_time(time1)
417 : :
418 : : ! perform QR decomposition to extract X_{k+1} and beta_{k}
419 : 1904 : call extract_QR(mpi_communicator, Hsize,nseeds,rk,beta(:,:,k))
420 : :
421 : 1904 : call cpu_time(time2)
422 : 1904 : list_time(itime) = list_time(itime) + time2-time1
423 : : ! copy the Q matrix (written on rk) in xk, which becomes X_{k+1}
424 [ + + + + ]: 384397 : xk(:,:) = rk(:,:)
425 : :
426 : :
427 : : end do !end loop on k
428 : :
429 : : ! overwrite the seeds with the last vector block.
430 [ + + + + ]: 35569 : seeds(:,:) = xk(:,:)
431 : :
432 [ - + ]: 173 : ABI_FREE( xk )
433 [ - + ]: 173 : ABI_FREE( xkm1)
434 [ - + ]: 173 : ABI_FREE( rk )
435 : 173 : call cpu_time(total_time2)
436 : :
437 : 173 : list_time(7) = total_time2-total_time1
438 : :
439 : 173 : call write_block_lanczos_timing_log(list_time,ntime)
440 : :
441 : 173 : ABI_FREE(list_time)
442 : :
443 : 173 : end subroutine block_lanczos_algorithm
444 : : !!***
445 : :
446 : : !!****f* m_gwls_GWlanczos/diagonalize_lanczos_banded
447 : : !! NAME
448 : : !! diagonalize_lanczos_banded
449 : : !!
450 : : !! FUNCTION
451 : : !! .
452 : : !!
453 : : !! INPUTS
454 : : !!
455 : : !! OUTPUT
456 : : !!
457 : : !! SOURCE
458 : :
459 : 177 : subroutine diagonalize_lanczos_banded(kmax,nseeds,Hsize,alpha,beta,Lbasis,eigenvalues,debug)
460 : : !-----------------------------------------------------------------------------------
461 : : ! Given the result of the Lanczos algorithm, this subroutine diagonalize the banded
462 : : ! matrix as well as updates the basis.
463 : : !-----------------------------------------------------------------------------------
464 : : integer, intent(in) :: kmax ! number of Lanczos blocks
465 : : integer, intent(in) :: nseeds ! size of each blocks
466 : : integer, intent(in) :: Hsize ! size of the Hilbert space in which the matrix lives
467 : : logical, intent(in) :: debug
468 : :
469 : : complex(dp), intent(in) :: alpha(nseeds,nseeds,kmax) ! the alpha array from the Lanczos algorithm
470 : : complex(dp), intent(in) :: beta (nseeds,nseeds,kmax) ! the beta array from the Lanczos algorithm
471 : :
472 : : complex(dp), intent(inout) :: Lbasis(Hsize,nseeds*kmax) ! array containing the Lanczos basis
473 : :
474 : :
475 : : real(dp), intent(out) :: eigenvalues(nseeds*kmax)
476 : :
477 : :
478 : : ! local variables
479 : :
480 : : integer :: kd ! number of superdiagonal above the diagonal in banded storage
481 : : integer :: ldab ! dimension of banded storage matrix
482 : :
483 : 177 : complex(dp), allocatable :: band_storage_matrix(:,:)
484 : 177 : complex(dp), allocatable :: saved_band_storage_matrix(:,:)
485 : :
486 : 177 : complex(dp), allocatable :: eigenvectors(:,:)
487 : :
488 : 177 : complex(dp), allocatable :: Lbasis_tmp(:,:)
489 : :
490 : : integer :: i, j
491 : : integer :: k
492 : : integer :: s1, s2
493 : : integer :: info
494 : :
495 : :
496 : 177 : complex(dp), allocatable :: work(:)
497 : 177 : real(dp), allocatable :: rwork(:)
498 : :
499 : : integer :: io_unit
500 : : character(128) :: filename
501 : : logical :: file_exists
502 : :
503 : : integer :: debug_unit
504 : : character(50) :: debug_filename
505 : :
506 : : ! *************************************************************************
507 : :
508 : :
509 : :
510 : : ! number of superdiagonals
511 : 177 : kd = nseeds
512 : 177 : ldab = kd + 1
513 : :
514 [ - + + - : 708 : ABI_MALLOC( band_storage_matrix, (ldab,nseeds*kmax))
- + + - +
- + - - +
- + ]
515 [ - + + - : 531 : ABI_MALLOC(saved_band_storage_matrix, (ldab,nseeds*kmax))
- + + - -
+ - + ]
516 : : !---------------------------------------------------------
517 : : ! Store banded matrix in banded format
518 : : !---------------------------------------------------------
519 : : ! for UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd).
520 : :
521 [ + + + + ]: 6297 : band_storage_matrix(:,:) = cmplx_0
522 : :
523 : : !-----------------------------------------
524 : : ! Store the alpha and beta matrices
525 : : !-----------------------------------------
526 : :
527 : : ! loop on all blocks
528 [ - + ]: 1928 : do k=1,kmax
529 : :
530 : : ! alpha blocks
531 [ + + ]: 3912 : do s2 = 1, nseeds
532 : 1984 : j = (k-1)*nseeds+s2
533 : :
534 [ + + ]: 5980 : do s1 = s2, nseeds
535 : 2068 : i = j+s1-s2
536 : 4052 : band_storage_matrix(1+i-j,j) = alpha(s1,s2,k)
537 : : end do
538 : : end do
539 : :
540 : : ! exit when k = kmax, as this beta block does not contribute.
541 [ + + ]: 1928 : if (k .eq. kmax) exit
542 : :
543 : : ! beta blocks
544 [ + + ]: 3721 : do s2 = 1, nseeds
545 : 1793 : j = (k-1)*nseeds+s2
546 : :
547 [ + + ]: 5400 : do s1 = 1, s2
548 : 1856 : i = j+s1-s2+nseeds
549 : 3649 : band_storage_matrix(1+i-j,j) = beta(s1,s2,k)
550 : : end do
551 : :
552 : : end do
553 : : end do
554 : :
555 [ + + + + ]: 6297 : saved_band_storage_matrix(:,:) = band_storage_matrix(:,:)
556 : :
557 : : !-----------------------------------------
558 : : ! Diagonalize the banded matrix
559 : : !-----------------------------------------
560 : :
561 [ - + + - : 708 : ABI_MALLOC(eigenvectors, (nseeds*kmax,nseeds*kmax))
- + + - +
- + - - +
- + ]
562 : :
563 [ - + + - : 531 : ABI_MALLOC(work,(nseeds*kmax))
+ - + - -
+ - + ]
564 [ + - - + : 531 : ABI_MALLOC(rwork,(3*nseeds*kmax-2))
+ - + - +
- - + -
+ ]
565 : :
566 : : call ZHBEV( 'V', & ! compute eigenvalues and eigenvectors
567 : : 'L', & ! lower triangular part of matrix is stored in banded_matrix
568 : : nseeds*kmax, & ! dimension of matrix
569 : : kd, & ! number of superdiagonals in banded matrix
570 : : band_storage_matrix, & ! matrix in banded storage
571 : : ldab, & ! leading dimension of banded_matrix
572 : : eigenvalues, & ! eigenvalues of matrix
573 : : eigenvectors, & ! eigenvectors of matrix
574 : : nseeds*kmax, & ! dimension of eigenvector matrix
575 : 177 : work, rwork, info ) ! work arrays and info
576 : :
577 : :
578 [ - + ]: 177 : if ( info /= 0) then
579 : 0 : debug_unit = get_unit()
580 : 0 : write(debug_filename,'(A,I4.4,A)') 'LAPACK_DEBUG_PROC=',mpi_enreg%me,'.log'
581 : :
582 : 0 : open(debug_unit,file=trim(debug_filename),status='unknown')
583 : :
584 : 0 : write(debug_unit,'(A)') '*********************************************************************************************'
585 : 0 : write(debug_unit,'(A,I4,A)') '* ERROR: info = ',info,' in ZHBEV (1), gwls_GWlanczos'
586 : 0 : write(debug_unit,'(A)') '*********************************************************************************************'
587 : :
588 : 0 : close(debug_unit)
589 : :
590 : : end if
591 : :
592 : :
593 : :
594 : : !----------------------------------------------------------------------------------
595 : : ! update the Lanczos basis to reflect diagonalization of T matrix
596 : : !
597 : : ! Note that by definition
598 : : !
599 : : ! Q^H . A . Q = T ==> A = Q . T . Q^H
600 : : !
601 : : ! where Q (Lbasis) contains the Lanczos basis.
602 : : !
603 : : ! Diagonalizing T, ie T = U . LAMBDA . U^H leads to
604 : : !
605 : : ! A = [ Q.U] . LAMBDA . [Q.U]^H
606 : : !
607 : : ! The updated basis is thus Q.U == Lbasis . eigenvectors
608 : : !----------------------------------------------------------------------------------
609 : :
610 : : ! NEVER use matmul!!! It sends temporary arrays to the stack, which can be much smaller
611 : : ! than needed; this leads to mysterious segfaults!
612 : :
613 : : ! Lbasis = matmul(Lbasis,eigenvectors)
614 : :
615 : : ! use temporary array, which is PROPERLY ALLOCATED, to perform matrix multiplication
616 [ - + + - : 708 : ABI_MALLOC(Lbasis_tmp, (Hsize,nseeds*kmax))
- + + - +
- + - - +
- + ]
617 : :
618 : : ! Compute C = A * B, where A = Lbasis, B = eigenvectors, and C = Lbasis_tmp
619 : : call ZGEMM( 'N', & ! leave array A as is
620 : : 'N', & ! leave array B as is
621 : : Hsize, & ! number of rows of A
622 : : nseeds*kmax, & ! number of columns of B
623 : : nseeds*kmax, & ! number of columns of A /rows of B
624 : : cmplx_1, & ! constant alpha
625 : : Lbasis, & ! matrix A
626 : : Hsize, & ! LDA
627 : : eigenvectors, & ! matrix B
628 : : nseeds*kmax, & ! LDB
629 : : cmplx_0, & ! constant beta
630 : : Lbasis_tmp, & ! matrix C
631 : 177 : Hsize) ! LDC
632 : :
633 : : ! overwrite initial array
634 [ + + + + ]: 388689 : Lbasis(:,:) = Lbasis_tmp(:,:)
635 : :
636 : :
637 [ - + ]: 177 : ABI_FREE(Lbasis_tmp)
638 : :
639 [ - + - - ]: 177 : if ( debug .and. mpi_enreg%me == 0) then
640 : : !----------------------------------------------------------------------------------
641 : : ! For the purpose of debugging, print relevant results to file to check
642 : : ! data consistency. This may not be necessary once the code has been shown to
643 : : ! work properly.
644 : : !----------------------------------------------------------------------------------
645 : :
646 : 0 : io_unit = get_unit()
647 : 0 : i = 0
648 : 0 : file_exists = .true.
649 [ # # ]: 0 : do while (file_exists)
650 : 0 : i = i+1
651 : 0 : write(filename,'(A,I0.4,A)') "diagonalize_banded_matrix_",i,".log"
652 : 0 : inquire(file=filename,exist=file_exists)
653 : : end do
654 : :
655 : :
656 : 0 : open(io_unit,file=filename,status=files_status_new)
657 : 0 : write(io_unit,10) "#======================================================================================="
658 : 0 : write(io_unit,10) "# "
659 : 0 : write(io_unit,10) "# This file contains information pertaining to the diagonalization of a banded "
660 : 0 : write(io_unit,10) "# matrix, expressed in terms of the Lanczos alpha and beta block arrays. "
661 : 0 : write(io_unit,10) "# "
662 : 0 : write(io_unit,10) "#======================================================================================="
663 : 0 : write(io_unit,10) "# "
664 : 0 : write(io_unit,12) "# diagonalization info : ",info," "
665 : 0 : write(io_unit,10) "# "
666 : 0 : write(io_unit,10) "# l lambda_l "
667 : 0 : write(io_unit,10) "#======================================================================================="
668 : :
669 [ # # ]: 0 : do i = 1, nseeds*kmax
670 : 0 : write(io_unit,13) i, eigenvalues(i)
671 : : end do
672 : :
673 : 0 : write(io_unit,10) " "
674 : 0 : write(io_unit,10) "# "
675 : 0 : write(io_unit,10) "# alpha and beta blocks "
676 : 0 : write(io_unit,10) "# "
677 : 0 : write(io_unit,10) "#======================================================================================="
678 : :
679 : : ! loop on all blocks
680 [ # # ]: 0 : do k=1,kmax
681 : 0 : write(io_unit,10) "# "
682 : 0 : write(io_unit,12) "# block k = ",k," "
683 : 0 : write(io_unit,10) "# "
684 : 0 : write(io_unit,15) "# alpha: ||alpha^H-alpha|| = ", &
685 [ # # # # ]: 0 : sqrt(sum(abs(alpha(:,:,k)-transpose(conjg(alpha(:,:,k))))**2))
686 [ # # ]: 0 : do s1 = 1, nseeds
687 : 0 : write(io_unit,14) alpha(s1,:,k)
688 : : end do
689 : :
690 : 0 : write(io_unit,10) "# "
691 : 0 : write(io_unit,10) "# beta "
692 [ # # ]: 0 : do s1 = 1, nseeds
693 : 0 : write(io_unit,14) beta(s1,:,k)
694 : : end do
695 : :
696 : :
697 : : end do
698 : :
699 : :
700 : :
701 : :
702 : 0 : write(io_unit,10) "# "
703 : 0 : write(io_unit,10) "# band storage matrix: "
704 : 0 : write(io_unit,10) "#======================================================================================="
705 : :
706 [ # # ]: 0 : do i = 1, ldab
707 : 0 : write(io_unit,14) saved_band_storage_matrix(i,:)
708 : : end do
709 : :
710 : 0 : close(io_unit)
711 : : end if
712 : :
713 : :
714 : : ! clean up memory
715 [ - + ]: 177 : ABI_FREE(eigenvectors)
716 [ - + ]: 177 : ABI_FREE( work)
717 [ - + ]: 177 : ABI_FREE(rwork)
718 [ - + ]: 177 : ABI_FREE(band_storage_matrix)
719 [ - + ]: 177 : ABI_FREE(saved_band_storage_matrix)
720 : :
721 : :
722 : : 10 format(A)
723 : : 12 format(A,I5,A)
724 : : 13 format(I5,5X,F24.12)
725 : : 14 format(4X,1000(F12.8,SP,F12.8,1X,'i',2X))
726 : : 15 format(A,ES24.8)
727 : :
728 : 177 : end subroutine diagonalize_lanczos_banded
729 : : !!***
730 : :
731 : : end module m_gwls_GWlanczos
732 : : !!***
|