10
0
mirror of https://github.com/LCPQ/quantum_package synced 2024-06-26 23:22:18 +02:00
quantum_package/src/Dets/davidson.irp.f

278 lines
7.7 KiB
FortranFixed
Raw Normal View History

BEGIN_PROVIDER [ integer, davidson_iter_max]
implicit none
BEGIN_DOC
! Max number of Davidson iterations
END_DOC
davidson_iter_max = 100
END_PROVIDER
BEGIN_PROVIDER [ integer, davidson_sze_max]
implicit none
BEGIN_DOC
! Max number of Davidson sizes
END_DOC
ASSERT (davidson_sze_max <= davidson_iter_max)
davidson_sze_max = 8
END_PROVIDER
subroutine davidson_diag(dets_in,u_in,energies,dim_in,sze,N_st,Nint)
use bitmasks
implicit none
BEGIN_DOC
! Davidson diagonalization.
!
! dets_in : bitmasks corresponding to determinants
!
! u_in : guess coefficients on the various states. Overwritten
! on exit
!
! dim_in : leftmost dimension of u_in
!
! sze : Number of determinants
!
! N_st : Number of eigenstates
!
! Initial guess vectors are not necessarily orthonormal
END_DOC
integer, intent(in) :: dim_in, sze, N_st, Nint
integer(bit_kind), intent(in) :: dets_in(Nint,2,sze)
double precision, intent(inout) :: u_in(dim_in,N_st)
double precision, intent(out) :: energies(N_st)
integer :: iter
2014-05-15 00:28:25 +02:00
integer :: i,j,k,l,m
logical :: converged
double precision :: overlap(N_st,N_st)
double precision :: u_dot_v, u_dot_u
integer, allocatable :: kl_pairs(:,:)
integer :: k_pairs, kl
integer :: iter2
double precision, allocatable :: W(:,:,:), H_jj(:), U(:,:,:), R(:,:)
double precision, allocatable :: y(:,:,:,:), h(:,:,:,:), lambda(:)
double precision :: diag_h_mat_elem
double precision :: residual_norm(N_st)
PROVIDE ref_bitmask_energy
allocate( &
kl_pairs(2,N_st*(N_st+1)/2), &
H_jj(sze), &
W(sze,N_st,davidson_sze_max), &
U(sze,N_st,davidson_sze_max), &
R(sze,N_st), &
h(N_st,davidson_sze_max,N_st,davidson_sze_max), &
y(N_st,davidson_sze_max,N_st,davidson_sze_max), &
lambda(N_st*davidson_sze_max))
ASSERT (N_st > 0)
ASSERT (sze > 0)
ASSERT (Nint > 0)
ASSERT (Nint == N_int)
2014-05-15 00:28:25 +02:00
! Initialization
! ==============
k_pairs=0
do l=1,N_st
do k=1,l
k_pairs+=1
kl_pairs(1,k_pairs) = k
kl_pairs(2,k_pairs) = l
enddo
enddo
2014-05-15 00:28:25 +02:00
!$OMP PARALLEL DEFAULT(NONE) &
!$OMP SHARED(U,sze,N_st,overlap,kl_pairs,k_pairs, &
!$OMP H_jj,Nint,dets_in,u_in) &
!$OMP PRIVATE(k,l,kl,i)
!$OMP DO
do i=1,sze
H_jj(i) = diag_h_mat_elem(dets_in(1,1,i),Nint)
enddo
!$OMP END DO NOWAIT
! Orthonormalize initial guess
! ============================
!$OMP DO
do kl=1,k_pairs
k = kl_pairs(1,kl)
l = kl_pairs(2,kl)
2014-05-15 00:28:25 +02:00
if (k/=l) then
overlap(k,l) = u_dot_v(U_in(1,k),U_in(1,l),sze)
overlap(l,k) = overlap(k,l)
else
overlap(k,k) = u_dot_u(U_in(1,k),sze)
endif
enddo
2014-05-15 00:28:25 +02:00
!$OMP END DO
!$OMP END PARALLEL
2014-05-15 00:28:25 +02:00
call ortho_lowdin(overlap,size(overlap,1),N_st,U_in,size(U_in,1),sze)
! Davidson iterations
! ===================
converged = .False.
2014-05-15 00:28:25 +02:00
do while (.not.converged)
2014-05-15 00:28:25 +02:00
!$OMP PARALLEL DEFAULT(NONE) &
!$OMP PRIVATE(k,i) SHARED(U,u_in,sze,N_st)
do k=1,N_st
2014-05-15 00:28:25 +02:00
!$OMP DO
do i=1,sze
U(i,k,1) = u_in(i,k)
enddo
!$OMP END DO
enddo
2014-05-15 00:28:25 +02:00
!$OMP END PARALLEL
2014-05-15 00:28:25 +02:00
do iter=1,davidson_sze_max-1
! print *, '***************'
! do i=1,iter
! do k=1,N_st
! do j=1,iter
! do l=1,N_st
! print '(4(I4,X),F16.8)', i,j,k,l, u_dot_v(U(1,k,i),U(1,l,j),sze)
! enddo
! enddo
! enddo
! enddo
! print *, '***************'
! Compute W_k = H |u_k>
! ----------------------
do k=1,N_st
call H_u_0(W(1,k,iter),U(1,k,iter),H_jj,sze,dets_in,Nint)
2014-05-15 00:28:25 +02:00
enddo
! Compute h_kl = <u_k | W_l> = <u_k| H |u_l>
! -------------------------------------------
do l=1,N_st
do k=1,N_st
do iter2=1,iter-1
h(k,iter2,l,iter) = u_dot_v(U(1,k,iter2),W(1,l,iter),sze)
2014-05-15 00:28:25 +02:00
h(k,iter,l,iter2) = h(k,iter2,l,iter)
enddo
enddo
do k=1,l
h(k,iter,l,iter) = u_dot_v(U(1,k,iter),W(1,l,iter),sze)
2014-05-15 00:28:25 +02:00
h(l,iter,k,iter) = h(k,iter,l,iter)
enddo
enddo
2014-05-15 00:28:25 +02:00
! Diagonalize h
! -------------
call lapack_diag(lambda,y,h,N_st*davidson_sze_max,N_st*iter)
! Express eigenvectors of h in the determinant basis
! --------------------------------------------------
! call dgemm ( 'N','N', sze, N_st*iter, N_st, &
! 1.d0, U(1,1,1), size(U,1), y(1,1,1,1), size(y,1)*size(y,2), &
! 0.d0, U(1,1,iter+1), size(U,1) )
2014-05-15 00:28:25 +02:00
do k=1,N_st
do i=1,sze
U(i,k,iter+1) = 0.d0
W(i,k,iter+1) = 0.d0
do l=1,N_st
do iter2=1,iter
U(i,k,iter+1) = U(i,k,iter+1) + U(i,l,iter2)*y(l,iter2,k,1)
W(i,k,iter+1) = W(i,k,iter+1) + W(i,l,iter2)*y(l,iter2,k,1)
2014-05-15 00:28:25 +02:00
enddo
enddo
enddo
enddo
2014-05-15 00:28:25 +02:00
! Compute residual vector
! -----------------------
do k=1,N_st
do i=1,sze
R(i,k) = lambda(k) * U(i,k,iter+1) - W(i,k,iter+1)
2014-05-15 00:28:25 +02:00
enddo
residual_norm(k) = u_dot_u(R(1,k),sze)
enddo
2014-05-17 14:20:55 +02:00
print '(I3,15(F16.8,x))', iter, lambda(1:N_st) + nuclear_repulsion
print '(3x,15(E16.5,x))', residual_norm(1:N_st)
2014-05-15 00:28:25 +02:00
2014-05-17 14:20:55 +02:00
converged = maxval(residual_norm) < 1.d-10
2014-05-15 00:28:25 +02:00
if (converged) then
exit
endif
! Davidson step
! -------------
do k=1,N_st
do i=1,sze
U(i,k,iter+1) = 1.d0/(lambda(k) - H_jj(i)) * R(i,k)
enddo
enddo
! Gram-Schmidt
! ------------
double precision :: c
do k=1,N_st
do iter2=1,iter
do l=1,N_st
2014-05-15 00:28:25 +02:00
c = u_dot_v(U(1,k,iter+1),U(1,l,iter2),sze)
do i=1,sze
U(i,k,iter+1) -= c * U(i,l,iter2)
enddo
enddo
enddo
2014-05-15 00:28:25 +02:00
do l=1,k-1
c = u_dot_v(U(1,k,iter+1),U(1,l,iter+1),sze)
do i=1,sze
U(i,k,iter+1) -= c * U(i,l,iter+1)
enddo
enddo
call normalize( U(1,k,iter+1), sze )
enddo
enddo
2014-05-15 00:28:25 +02:00
if (.not.converged) then
iter = davidson_sze_max-1
endif
2014-05-15 00:28:25 +02:00
! Re-contract to u_in
! -----------
do k=1,N_st
2014-05-15 00:28:25 +02:00
energies(k) = lambda(k)
do i=1,sze
2014-05-15 00:28:25 +02:00
u_in(i,k) = 0.d0
do iter2=1,iter
do l=1,N_st
u_in(i,k) += U(i,l,iter2)*y(l,iter2,k,1)
enddo
enddo
enddo
enddo
enddo
2014-05-15 00:28:25 +02:00
deallocate ( &
kl_pairs, &
H_jj, &
W, &
U, &
R, &
h, &
y, &
lambda &
)
end