11! > \namespace Davidson eigensolver
22! > \author Felipe Zapata
3+ ! > The current implementation uses a general davidson algorithm, meaning
4+ ! > that it compute all the eigenvalues simultaneusly using a variable size block approach.
5+ ! > The family of Davidson algorithm only differ in the way that the correction
6+ ! > vector is computed.
7+ ! > Computed pairs of eigenvalues/eigenvectors are deflated using algorithm
8+ ! > described at: https://doi.org/10.1023/A:101919970
9+
10+
311module davidson_dense
412 ! > Submodule containing the implementation of the Davidson diagonalization method
513 ! > for dense matrices
614 use numeric_kinds, only: dp
715 use lapack_wrapper, only: lapack_generalized_eigensolver, lapack_matmul, lapack_matrix_vector, &
8- lapack_qr, lapack_solver
9- use array_utils, only: concatenate, eye, norm
16+ lapack_qr, lapack_solver, lapack_sort
17+ use array_utils, only: concatenate, diagonal, eye, generate_preconditioner , norm
1018
1119 implicit none
1220
@@ -41,11 +49,8 @@ end function compute_correction_generalized_dense
4149
4250 subroutine generalized_eigensolver_dense (mtx , eigenvalues , ritz_vectors , lowest , method , max_iters , &
4351 tolerance , iters , max_dim_sub , stx )
44- ! > The current implementation uses a general davidson algorithm, meaning
45- ! > that it compute all the eigenvalues simultaneusly using a block approach.
46- ! > The family of Davidson algorithm only differ in the way that the correction
47- ! > vector is computed.
48-
52+ ! > Implementation storing in memory the initial densed matrix mtx.
53+
4954 ! > \param[in] mtx: Matrix to diagonalize
5055 ! > \param[in, opt] Optional matrix to solve the general eigenvalue problem:
5156 ! > \f$ mtx \lambda = V stx \lambda \f$
@@ -78,6 +83,7 @@ subroutine generalized_eigensolver_dense(mtx, eigenvalues, ritz_vectors, lowest,
7883
7984 ! local variables
8085 integer :: i, j, dim_sub, max_dim
86+ integer :: n_converged ! Number of converged eigenvalue/eigenvector pairs
8187
8288 ! Basis of subspace of approximants
8389 real (dp), dimension (size (mtx, 1 )) :: guess, rs
@@ -87,12 +93,22 @@ subroutine generalized_eigensolver_dense(mtx, eigenvalues, ritz_vectors, lowest,
8793 real (dp), dimension (:), allocatable :: eigenvalues_sub
8894 real (dp), dimension (:, :), allocatable :: correction, eigenvectors_sub, mtx_proj, stx_proj, V
8995
96+ ! Diagonal matrix
97+ real (dp), dimension (size (mtx, 1 )) :: d
98+
9099 ! generalize problem
91100 logical :: gev
92101
102+ ! indices of the eigenvalues/eigenvectors pair that have not converged
103+ logical , dimension (lowest) :: has_converged
104+
93105 ! Iteration subpsace dimension
94106 dim_sub = lowest * 2
95107
108+ ! Initial number of converged eigenvalue/eigenvector pairs
109+ n_converged = 0
110+ has_converged = .False.
111+
96112 ! maximum dimension of the basis for the subspace
97113 if (present (max_dim_sub)) then
98114 max_dim = max_dim_sub
@@ -104,8 +120,10 @@ subroutine generalized_eigensolver_dense(mtx, eigenvalues, ritz_vectors, lowest,
104120 gev = present (stx)
105121
106122 ! 1. Variables initialization
107- V = eye(size (ritz_vectors, 1 ), dim_sub) ! Initial orthonormal basis
108-
123+ ! Select the initial ortogonal subspace based on lowest elements
124+ ! of the diagonal of the matrix
125+ d = diagonal(mtx)
126+ V = generate_preconditioner(d, dim_sub)
109127
110128 ! 2. Generate subpace matrix problem by projecting into V
111129 mtx_proj = lapack_matmul(' T' , ' N' , V, lapack_matmul(' N' , ' N' , mtx, V))
@@ -145,9 +163,16 @@ subroutine generalized_eigensolver_dense(mtx, eigenvalues, ritz_vectors, lowest,
145163 end if
146164 rs = lapack_matrix_vector(' N' , mtx, ritz_vectors(:, j)) - guess
147165 errors(j) = norm(rs)
166+ ! Check which eigenvalues has converged
167+ if (errors(j) < tolerance) then
168+ has_converged(j) = .true.
169+ end if
148170 end do
149-
150- if (all (errors < tolerance)) then
171+
172+ ! Count converged pairs of eigenvalues/eigenvectors
173+ n_converged = n_converged + count (errors < tolerance)
174+
175+ if (all (has_converged)) then
151176 iters = i
152177 exit
153178 end if
@@ -197,7 +222,8 @@ subroutine generalized_eigensolver_dense(mtx, eigenvalues, ritz_vectors, lowest,
197222 end do outer_loop
198223
199224 ! 8. Check convergence
200- if (i > max_iters / dim_sub) then
225+ if (i > max_iters) then
226+ iters = i
201227 print * , " Warning: Algorithm did not converge!!"
202228 end if
203229
@@ -265,7 +291,7 @@ module davidson_free
265291 use numeric_kinds, only: dp
266292 use lapack_wrapper, only: lapack_generalized_eigensolver, lapack_matmul, lapack_matrix_vector, &
267293 lapack_qr, lapack_solver
268- use array_utils, only: concatenate, eye , norm
294+ use array_utils, only: concatenate, generate_preconditioner , norm
269295 use davidson_dense, only: generalized_eigensolver_dense
270296 implicit none
271297
@@ -343,7 +369,7 @@ end function fun_stx_gemv
343369
344370 ! ! Basis of subspace of approximants
345371 real (dp), dimension (size (ritz_vectors, 1 ),1 ) :: guess, rs
346- real (dp), dimension (size (ritz_vectors, 1 ) ) :: diag_mtx, diag_stx
372+ real (dp), dimension (size (ritz_vectors, 1 ) ) :: diag_mtx, diag_stx, copy_d
347373 real (dp), dimension (lowest):: errors
348374
349375 ! ! Working arrays
@@ -368,7 +394,10 @@ end function fun_stx_gemv
368394 diag_stx = extract_diagonal_free(fun_stx_gemv,dim_mtx)
369395
370396 ! 1. Variables initialization
371- V = eye(dim_mtx, dim_sub) ! Initial orthonormal basis
397+ ! Select the initial ortogonal subspace based on lowest elements
398+ ! of the diagonal of the matrix
399+ copy_d = diag_mtx
400+ V = generate_preconditioner(copy_d, dim_sub) ! Initial orthonormal basis
372401
373402 ! 2. Generate subspace matrix problem by projecting into V
374403 mtx_proj = lapack_matmul(' T' , ' N' , V, fun_mtx_gemv(V))
@@ -757,7 +786,7 @@ function compute_DPR_generalized_dense(mtx, V, eigenvalues, eigenvectors, stx) r
757786 real (dp), dimension (:, :), intent (in ) :: mtx, V, eigenvectors
758787 real (dp), dimension (:, :), intent (in ), optional :: stx
759788 real (dp), dimension (size (mtx, 1 ), size (V, 2 )) :: correction
760-
789+
761790 ! local variables
762791 integer :: ii,j, m
763792 real (dp), dimension (size (mtx, 1 ), size (mtx, 2 )) :: diag, arr
@@ -780,12 +809,12 @@ function compute_DPR_generalized_dense(mtx, V, eigenvalues, eigenvectors, stx) r
780809 correction(:, j) = lapack_matrix_vector(' N' , arr, vec)
781810
782811 do ii= 1 ,size (correction,1 )
783- if (gev) then
784- correction(ii, j) = correction(ii, j) / (eigenvalues(j) * stx(ii,ii) - mtx(ii, ii))
785- else
786- correction(ii, j) = correction(ii, j) / (eigenvalues(j) - mtx(ii, ii))
787- end if
788- end do
812+ if (gev) then
813+ correction(ii, j) = correction(ii, j) / (eigenvalues(j) * stx(ii,ii) - mtx(ii, ii))
814+ else
815+ correction(ii, j) = correction(ii, j) / (eigenvalues(j) - mtx(ii, ii))
816+ endif
817+ end do
789818 end do
790819
791820 end function compute_DPR_generalized_dense
0 commit comments