LCOV - code coverage report
Current view: top level - src/70_gw - m_gwls_GWlanczos.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 72.6 % 201 146
Test Date: 2026-09-19 17:42:43 Functions: 100.0 % 3 3

            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              : !!***
        

Generated by: LCOV version 2.3-1