LCOV - code coverage report
Current view: top level - src/70_gw - m_gwls_utility.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 79 79
Test Date: 2026-11-09 22:30:52 Functions: 100.0 % 4 4
Branches: 60.6 % 104 63

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_gwls_utility
       2                 :             : !! NAME
       3                 :             : !! m_gwls_utility
       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                 :             : 
      23                 :             : !---------------------------------------------------------------------
      24                 :             : !  Utility modules, which are not directly related to the
      25                 :             : !  problem to be solved.
      26                 :             : !---------------------------------------------------------------------
      27                 :             : 
      28                 :             : module m_gwls_utility
      29                 :             : !----------------------------------------------------------------------------------------------------
      30                 :             : ! This module contains useful functions and subroutines, which are not necessarily numerical
      31                 :             : ! in nature, for timing, opening files, etc...
      32                 :             : !----------------------------------------------------------------------------------------------------
      33                 :             : 
      34                 :             : ! abinit modules
      35                 :             : use defs_basis
      36                 :             : use m_abicore
      37                 :             : use m_xmpi
      38                 :             : 
      39                 :             : use m_abi_linalg
      40                 :             : use m_io_tools, only : get_unit
      41                 :             : 
      42                 :             : implicit none
      43                 :             : 
      44                 :             : private
      45                 :             : 
      46                 :             : complex(dp), public, parameter :: cmplx_i = (0.0_dp,1.0_dp)
      47                 :             : complex(dp), public, parameter :: cmplx_1 = (1.0_dp,0.0_dp)
      48                 :             : complex(dp), public, parameter :: cmplx_0 = (0.0_dp,0.0_dp)
      49                 :             : 
      50                 :             : logical, public  :: master_debug
      51                 :             : character(len=100), public :: files_status_new='new'
      52                 :             : character(len=100), public :: files_status_old='unknown'
      53                 :             : 
      54                 :             : public :: driver_invert_positive_definite_hermitian_matrix
      55                 :             : public :: ritz_analysis_general, orthogonalize
      56                 :             : public :: complex_vector_product
      57                 :             : !!***
      58                 :             : contains
      59                 :             : 
      60                 :             : !!****f* m_gwls_utility/complex_vector_product
      61                 :             : !! NAME
      62                 :             : !!  complex_vector_product
      63                 :             : !!
      64                 :             : !! FUNCTION
      65                 :             : !!  .
      66                 :             : !!
      67                 :             : !! INPUTS
      68                 :             : !!
      69                 :             : !! OUTPUT
      70                 :             : !!
      71                 :             : !!
      72                 :             : !!
      73                 :             : !! SOURCE
      74                 :             : 
      75                 :        9848 : complex(dp) function complex_vector_product(v1,v2,l)
      76                 :             : !--------------------------------------------------------------------------
      77                 :             : ! This function computes the vector product of two complex vectors.
      78                 :             : !--------------------------------------------------------------------------
      79                 :             : integer,     intent(in)  :: l
      80                 :             : complex(dp),intent(in)  :: v1(l), v2(l)
      81                 :             : ! *************************************************************************
      82                 :             : 
      83         [ +  + ]:     1288680 : complex_vector_product = sum(conjg(v1(:))*v2(:))
      84                 :             : 
      85                 :        9848 : end function complex_vector_product
      86                 :             : !!***
      87                 :             : 
      88                 :             : !!****f* m_gwls_utility/orthogonalize
      89                 :             : !! NAME
      90                 :             : !!  orthogonalize
      91                 :             : !!
      92                 :             : !! FUNCTION
      93                 :             : !!  .
      94                 :             : !!
      95                 :             : !! INPUTS
      96                 :             : !!
      97                 :             : !! OUTPUT
      98                 :             : !!
      99                 :             : !! SOURCE
     100                 :             : 
     101                 :        1904 : subroutine orthogonalize(mpi_communicator, Hsize,Qsize,Xsize,Q,X)
     102                 :             : !--------------------------------------------------------------------------
     103                 :             : ! This function wraps the relevant LAPACK routines to perform
     104                 :             : !
     105                 :             : !                X = (1 - Q.Q^H ) . X
     106                 :             : !
     107                 :             : ! This essentially projects out  the subspace in Q from X.
     108                 :             : ! The array dimensions are:
     109                 :             : !
     110                 :             : !                                Q [ Hsize, Qsize]
     111                 :             : !                                X [ Hsize, Xsize]
     112                 :             : !                                Y [ Hsize, Xsize]
     113                 :             : !
     114                 :             : !  Hsize means "dimension of the Hilbert space", so typically the number
     115                 :             : !  of plane waves...
     116                 :             : !--------------------------------------------------------------------------
     117                 :             : integer,     intent(in)  :: mpi_communicator
     118                 :             : integer,     intent(in)  :: Hsize, Qsize, Xsize
     119                 :             : complex(dp),intent(in)  :: Q(Hsize,Qsize)
     120                 :             : complex(dp),intent(inout)  :: X(Hsize,Xsize)
     121                 :        1904 : complex(dp),allocatable :: C(:,:)
     122                 :             : 
     123                 :             : integer :: ierr
     124                 :             : 
     125                 :             : ! *************************************************************************
     126                 :             : 
     127                 :             : 
     128   [ -  +  +  -  :        7616 : ABI_MALLOC(C,(Qsize,Xsize))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     129                 :             : 
     130                 :             : ! Compute Q^dagger . X
     131                 :             : call ZGEMM(            'C',   & ! Hermitian conjugate the first array
     132                 :             : 'N',   & ! Leave second array as is
     133                 :             : Qsize,   & ! the number of rows of the  matrix op( A )
     134                 :             : Xsize,   & ! the number of columns of the  matrix op( B )
     135                 :             : Hsize,   & ! the number of columns of the  matrix op( A ) == rows of matrix op( B )
     136                 :             : cmplx_1,   & ! alpha constant
     137                 :             : Q,   & ! matrix A
     138                 :             : Hsize,   & ! LDA
     139                 :             : X,   & ! matrix B
     140                 :             : Hsize,   & ! LDB
     141                 :             : cmplx_0,   & ! beta constant
     142                 :             : C,   & ! matrix C
     143                 :        1904 : Qsize)     ! LDC
     144                 :             : 
     145                 :             : 
     146                 :        1904 : call xmpi_sum(C,mpi_communicator,ierr) ! sum on all processors working on FFT!
     147                 :             : 
     148                 :             : ! Compute X - Q.(Q^dagger . X)
     149                 :             : call ZGEMM(            'N',   & ! Leave first array as is
     150                 :             : 'N',   & ! Leave second array as is
     151                 :             : Hsize,   & ! the number of rows of the  matrix op( A )
     152                 :             : Xsize,   & ! the number of columns of the  matrix op( B )
     153                 :             : Qsize,   & ! the number of columns of the  matrix op( A ) == rows of matrix op( B )
     154                 :             : -cmplx_1,   & ! alpha constant
     155                 :             : Q,   & ! matrix A
     156                 :             : Hsize,   & ! LDA
     157                 :             : C,   & ! matrix B
     158                 :             : Qsize,   & ! LDB
     159                 :             : cmplx_1,   & ! beta constant
     160                 :             : X,   & ! matrix C
     161                 :        1904 : Hsize)     ! LDC
     162                 :             : 
     163         [ -  + ]:        1904 : ABI_FREE(C)
     164                 :             : 
     165                 :        1904 : end subroutine orthogonalize
     166                 :             : !!***
     167                 :             : 
     168                 :             : !!****f* m_gwls_utility/driver_invert_positive_definite_hermitian_matrix
     169                 :             : !! NAME
     170                 :             : !!  driver_invert_positive_definite_hermitian_matrix
     171                 :             : !!
     172                 :             : !! FUNCTION
     173                 :             : !!  .
     174                 :             : !!
     175                 :             : !! INPUTS
     176                 :             : !!
     177                 :             : !! OUTPUT
     178                 :             : !!
     179                 :             : !! SOURCE
     180                 :             : 
     181                 :         175 : subroutine driver_invert_positive_definite_hermitian_matrix(matrix,ldim)
     182                 :             : !----------------------------------------------------------------------------------------------------
     183                 :             : !        This is a utility-type subroutine, which encapsulates the many Lapack steps necessary
     184                 :             : !        to invert a positive definite hermitian matrix, and returns the full inverse to avoid
     185                 :             : !        errors!
     186                 :             : !
     187                 :             : !        The subroutine overwrites the input.
     188                 :             : !----------------------------------------------------------------------------------------------------
     189                 :             : integer     , intent(in)    :: ldim
     190                 :             : complex(dp), intent(inout) :: matrix(ldim,ldim)
     191                 :             : 
     192                 :             : ! local variables
     193                 :             : integer      :: i, j
     194                 :             : 
     195                 :             : 
     196                 :             : integer      :: info
     197                 :             : 
     198                 :             : ! *************************************************************************
     199                 :             : 
     200                 :             : 
     201                 :             : 
     202                 :             : ! First, peform a decomposition
     203                 :         175 : call abi_xpotrf( 'U', ldim, matrix, ldim, info )
     204                 :             : 
     205                 :             : ! Second, inverse the matrix in the new format
     206                 :         175 : call zpotri( 'U', ldim,matrix, ldim, info )
     207                 :             : 
     208                 :             : 
     209                 :             : ! Finally,  properly symmetrise the matrix so that it is hermitian!
     210                 :             : ! The upper triangular part of the matrix is correct; the lower triangular must be built
     211         [ +  + ]:        1571 : do j=1, ldim
     212         [ +  + ]:        6449 : do i=j+1, ldim
     213                 :        6274 : matrix(i,j)= conjg(matrix(j,i))
     214                 :             : end do
     215                 :             : end do
     216                 :             : 
     217                 :             : 
     218                 :         175 : end subroutine driver_invert_positive_definite_hermitian_matrix
     219                 :             : !!***
     220                 :             : 
     221                 :             : !!****f* m_gwls_utility/ritz_analysis_general
     222                 :             : !! NAME
     223                 :             : !!  ritz_analysis_general
     224                 :             : !!
     225                 :             : !! FUNCTION
     226                 :             : !!  .
     227                 :             : !!
     228                 :             : !! INPUTS
     229                 :             : !!
     230                 :             : !! OUTPUT
     231                 :             : !!
     232                 :             : !! SOURCE
     233                 :             : 
     234                 :           2 : subroutine ritz_analysis_general(mpi_communicator,matrix_function,lmax,Hsize,Lbasis,eigenvalues)
     235                 :             : !----------------------------------------------------------------------
     236                 :             : !
     237                 :             : ! This subroutine is mostly for testing purposes.
     238                 :             : !
     239                 :             : ! Given a matrix A_{NxN} which undergoes Lanczos analysis to yield
     240                 :             : ! a trigonal matrix T_{k x k}, for k lanczos steps, it is useful to
     241                 :             : ! test how well the eivenalues of T reproduce the eigenvalues of A.
     242                 :             : !
     243                 :             : ! Following Matrix computations by Golub and Van Loan, define
     244                 :             : !
     245                 :             : !                Q = [ |  |  ...  | ],        T = S^H.D.S,  D diagonal, S unitary
     246                 :             : !                    [ q1 q2 ...  qk]
     247                 :             : !                    [ |  |  ...  | ]
     248                 :             : !
     249                 :             : !                Y = Q.S
     250                 :             : !
     251                 :             : ! If tridiagonalisation was taken all the way to k = N, we would expect
     252                 :             : ! Y to contain the eigenvectors of A. It is useful to ask if, for a finite
     253                 :             : ! k, Y already contains good approximations to eigenvectors, by computing
     254                 :             : ! the Ritz residual,
     255                 :             : !
     256                 :             : !        Ri = || A.yi - di yi ||.
     257                 :             : !
     258                 :             : !        INPUTS:
     259                 :             : !                     matrix_function    : the function which yields the action
     260                 :             : !                                        of the implicit matrix on a vector
     261                 :             : !                        lmax            : the total number of Lanczos steps
     262                 :             : !                        Hsize           : the dimension of the Hilbert space
     263                 :             : !                        Lbasis          : the Y matrix
     264                 :             : !                       eigenvalues      : the computed approximate eigenvalues
     265                 :             : !                                        of the matrix
     266                 :             : !----------------------------------------------------------------------
     267                 :             : interface
     268                 :             :   subroutine matrix_function(v_out,v_in,l)
     269                 :             :   use defs_basis
     270                 :             : 
     271                 :             :   integer,     intent(in)  :: l
     272                 :             :   complex(dp), intent(out) :: v_out(l)
     273                 :             :   complex(dp), intent(in)  :: v_in(l)
     274                 :             : 
     275                 :             :   end subroutine matrix_function
     276                 :             : end interface
     277                 :             : 
     278                 :             : 
     279                 :             : integer,      intent(in)    :: Hsize, lmax , mpi_communicator
     280                 :             : complex(dp), intent(in)    :: Lbasis(Hsize,lmax)
     281                 :             : real(dp),     intent(in)    :: eigenvalues(lmax)
     282                 :             : 
     283                 :             : 
     284                 :             : ! local variables
     285                 :           2 : complex(dp),allocatable :: check_matrix(:,:)
     286                 :           2 : complex(dp),allocatable :: yl(:), rl(:), Ayl(:)
     287                 :             : 
     288                 :             : real(dp)     :: lambda_l
     289                 :             : real(dp)     :: check_norm
     290                 :             : integer      :: l, i
     291                 :             : 
     292                 :             : real(dp)     :: norm_ritz, norm_ritz_squared
     293                 :             : 
     294                 :             : character(128) :: filename
     295                 :             : logical        :: file_exists
     296                 :             : integer        :: io_unit
     297                 :             : integer        :: ierr
     298                 :             : integer        :: mpi_rank
     299                 :             : 
     300                 :             : logical        :: head_node
     301                 :             : 
     302                 :             : ! *************************************************************************
     303                 :             : 
     304   [ -  +  +  -  :           8 : ABI_MALLOC(check_matrix,(lmax,lmax))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     305   [ -  +  +  -  :           6 : ABI_MALLOC(yl,(Hsize))
          +  -  +  -  -  
                +  -  + ]
     306   [ -  +  +  -  :           4 : ABI_MALLOC(rl,(Hsize))
             -  +  -  + ]
     307   [ -  +  +  -  :           4 : ABI_MALLOC(Ayl,(Hsize))
             -  +  -  + ]
     308                 :             : 
     309                 :           2 : mpi_rank  = xmpi_comm_rank(mpi_communicator)
     310                 :             : 
     311                 :           2 : head_node = mpi_rank == 0
     312                 :             : 
     313         [ +  - ]:           2 : if (head_node) then
     314                 :           2 :   io_unit = get_unit()
     315                 :             : 
     316                 :           2 :   i = 0
     317                 :           2 :   file_exists = .true.
     318         [ +  + ]:           5 :   do while (file_exists)
     319                 :           3 :   i = i+1
     320                 :           3 :   write(filename,'(A,I0.4,A)') "General_Ritz_Analisis_",i,".log"
     321                 :           5 :   inquire(file=filename,exist=file_exists)
     322                 :             :   end do
     323                 :             : 
     324                 :             : 
     325                 :           2 :   open(io_unit,file=filename,status=files_status_new)
     326                 :             : 
     327                 :           2 :   write(io_unit,10) ''
     328                 :           2 :   write(io_unit,10) '#===================================================================================================='
     329                 :           2 :   write(io_unit,10) '# Entering ritz_analisis'
     330                 :           2 :   write(io_unit,10) '# '
     331                 :           2 :   write(io_unit,10) '#  parameters'
     332                 :           2 :   write(io_unit,16) '#          Dimension of Hilbert space    : ',Hsize
     333                 :           2 :   write(io_unit,16) '#          total number of Lanczos steps : ',lmax
     334                 :           2 :   write(io_unit,10) '# '
     335                 :           2 :   write(io_unit,10) '#===================================================================================================='
     336                 :           2 :   write(io_unit,10) ''
     337                 :           2 :   flush(io_unit)
     338                 :             : end if
     339                 :             : 
     340                 :             : ! NEVER use MATMUL! It stores temp arrays on stack, which kills executables compiled with intel!
     341                 :             : ! check_matrix(:,:) = matmul(transpose(conjg(Lbasis)),Lbasis)
     342                 :             : call ZGEMM(            'C',   & ! Hermitian conjugate the first array
     343                 :             : 'N',   & ! Leave second array as is
     344                 :             : lmax,   & ! the number of rows of the  matrix op( A )
     345                 :             : lmax,   & ! the number of columns of the  matrix op( B )
     346                 :             : Hsize,   & ! the number of columns of the  matrix op( A ) == rows of matrix op( B )
     347                 :             : cmplx_1,   & ! alpha constant
     348                 :             : Lbasis,   & ! matrix A
     349                 :             : Hsize,   & ! LDA
     350                 :             : Lbasis,   & ! matrix B
     351                 :             : Hsize,   & ! LDB
     352                 :             : cmplx_0,   & ! beta constant
     353                 :             : check_matrix,   & ! matrix C
     354                 :           2 : lmax)     ! LDC
     355                 :             : 
     356                 :             : 
     357                 :           2 : call xmpi_sum(check_matrix,mpi_communicator,ierr) ! sum on all processors working on FFT!
     358                 :             : 
     359         [ +  + ]:          18 : do l = 1, lmax
     360                 :          18 : check_matrix(l,l) =  check_matrix(l,l) - cmplx_1
     361                 :             : end do
     362   [ +  +  +  + ]:         146 : check_norm = sqrt(sum(abs(check_matrix(:,:))**2))
     363                 :             : 
     364                 :             : 
     365         [ +  - ]:           2 : if (head_node) then
     366                 :           2 :   write(io_unit,10) '#'
     367                 :           2 :   write(io_unit,11) '#  Is the basis orthonormal?   || I - Y^H . Y || = ',check_norm
     368                 :           2 :   write(io_unit,10) '#'
     369                 :           2 :   flush(io_unit)
     370                 :             : 
     371                 :             : 
     372                 :             :   ! Compute Ritz norms
     373                 :           2 :   write(io_unit,10) ''
     374                 :           2 :   write(io_unit,10) '#  Ritz analysis Lanczos Basis'
     375                 :           2 :   write(io_unit,10) "#   l               lambda_l                       || R_l ||                                         "
     376                 :           2 :   write(io_unit,10) '#===================================================================================================='
     377                 :           2 :   flush(io_unit)
     378                 :             : end if
     379                 :             : 
     380         [ +  + ]:          18 : do l = 1, lmax
     381                 :             : 
     382                 :          16 : lambda_l = eigenvalues(l)
     383                 :             : 
     384   [ -  +  +  + ]:        4144 : yl       = Lbasis(:,l)
     385                 :          16 : call matrix_function(Ayl,yl,Hsize)
     386   [ -  +  +  + ]:        4144 : rl       = Ayl - lambda_l*yl
     387                 :             : 
     388         [ +  + ]:        4128 : norm_ritz_squared = sum(abs(rl(:))**2)
     389                 :          16 : call xmpi_sum(norm_ritz_squared ,mpi_communicator,ierr)
     390                 :             : 
     391                 :          16 : norm_ritz = sqrt(norm_ritz_squared )
     392                 :             : 
     393                 :             : 
     394         [ +  - ]:          18 : if (head_node) write(io_unit,14) l, lambda_l, norm_ritz
     395                 :             : 
     396                 :             : end do
     397                 :             : 
     398         [ +  - ]:           2 : if (head_node) then
     399                 :           2 :   flush(io_unit)
     400                 :           2 :   close(io_unit)
     401                 :             : end if
     402                 :             : 
     403                 :             : 
     404         [ -  + ]:           2 : ABI_FREE(check_matrix)
     405         [ -  + ]:           2 : ABI_FREE(yl)
     406         [ -  + ]:           2 : ABI_FREE(rl)
     407         [ -  + ]:           2 : ABI_FREE(Ayl)
     408                 :             : 
     409                 :             : 
     410                 :             : 10 format(A)
     411                 :             : 11 format(A,ES24.16)
     412                 :             : 14 format(I5,2(5X,F24.12))
     413                 :             : 16 format(A,I5)
     414                 :             : 
     415                 :             : 
     416                 :           2 : end subroutine ritz_analysis_general
     417                 :             : !!***
     418                 :             : 
     419                 :             : end module m_gwls_utility
     420                 :             : 
     421                 :             : !!***
        

Generated by: LCOV version 2.3-1