From 5ada23842241b73a88dbac805a5d71861a630f8a Mon Sep 17 00:00:00 2001 From: Anthony Scemama Date: Fri, 30 Sep 2016 21:38:01 +0200 Subject: [PATCH] S2 is selected by Davidson --- src/Davidson/diagonalization_hs2.irp.f | 176 +++++++++++++++---------- src/Davidson/diagonalize_CI.irp.f | 69 +--------- 2 files changed, 112 insertions(+), 133 deletions(-) diff --git a/src/Davidson/diagonalization_hs2.irp.f b/src/Davidson/diagonalization_hs2.irp.f index 2c5c7387..769f6199 100644 --- a/src/Davidson/diagonalization_hs2.irp.f +++ b/src/Davidson/diagonalization_hs2.irp.f @@ -96,14 +96,15 @@ subroutine davidson_diag_hjj_sjj(dets_in,u_in,H_jj,S2_jj,energies,dim_in,sze,N_s integer :: k_pairs, kl integer :: iter2 - double precision, allocatable :: W(:,:,:), U(:,:,:), R(:,:), S(:,:,:) - double precision, allocatable :: y(:,:,:,:), h(:,:,:,:), lambda(:), s2(:) - double precision, allocatable :: c(:), H_small(:,:) + double precision, allocatable :: W(:,:), U(:,:), R(:,:), S(:,:) + double precision, allocatable :: y(:,:), h(:,:), lambda(:), s2(:) + double precision, allocatable :: c(:), s_(:,:), s_tmp(:,:) double precision :: diag_h_mat_elem double precision, allocatable :: residual_norm(:) character*(16384) :: write_buffer double precision :: to_print(3,N_st) double precision :: cpu, wall + integer :: shift, shift2 include 'constants.include.F' !DIR$ ATTRIBUTES ALIGN : $IRP_ALIGN :: U, W, R, S, y, h, lambda @@ -153,17 +154,18 @@ subroutine davidson_diag_hjj_sjj(dets_in,u_in,H_jj,S2_jj,energies,dim_in,sze,N_s allocate( & kl_pairs(2,N_st_diag*(N_st_diag+1)/2), & - W(sze_8,N_st_diag,davidson_sze_max), & - U(sze_8,N_st_diag,davidson_sze_max), & + W(sze_8,N_st_diag*davidson_sze_max), & + U(sze_8,N_st_diag*davidson_sze_max), & R(sze_8,N_st_diag), & - S(sze_8,N_st_diag,davidson_sze_max), & - h(N_st_diag,davidson_sze_max,N_st_diag,davidson_sze_max), & - y(N_st_diag,davidson_sze_max,N_st_diag,davidson_sze_max), & + S(sze_8,N_st_diag*davidson_sze_max), & + h(N_st_diag*davidson_sze_max,N_st_diag*davidson_sze_max), & + y(N_st_diag*davidson_sze_max,N_st_diag*davidson_sze_max), & + s_(N_st_diag*davidson_sze_max,N_st_diag*davidson_sze_max), & + s_tmp(N_st_diag*davidson_sze_max,N_st_diag*davidson_sze_max), & residual_norm(N_st_diag), & overlap(N_st_diag,N_st_diag), & c(N_st_diag*davidson_sze_max), & - H_small(N_st_diag,N_st_diag), & - s2(N_st_diag), & + s2(N_st_diag*davidson_sze_max), & lambda(N_st_diag*davidson_sze_max)) ASSERT (N_st > 0) @@ -203,16 +205,21 @@ subroutine davidson_diag_hjj_sjj(dets_in,u_in,H_jj,S2_jj,energies,dim_in,sze,N_s do k=1,N_st_diag do i=1,sze - U(i,k,1) = u_in(i,k) + U(i,k) = u_in(i,k) enddo enddo do iter=1,davidson_sze_max-1 + shift = N_st_diag*(iter-1) + shift2 = N_st_diag*iter + + ! Compute |W_k> = \sum_i |i> ! ----------------------------------------- - call H_S2_u_0_nstates(W(1,1,iter),S(1,1,iter),U(1,1,iter),H_jj,S2_jj,sze,dets_in,Nint,N_st_diag,sze_8) + + call H_S2_u_0_nstates(W(1,shift+1),S(1,shift+1),U(1,shift+1),H_jj,S2_jj,sze,dets_in,Nint,N_st_diag,sze_8) ! Compute h_kl = = @@ -232,56 +239,95 @@ subroutine davidson_diag_hjj_sjj(dets_in,u_in,H_jj,S2_jj,energies,dim_in,sze,N_s ! enddo ! enddo - call dgemm('T','N', N_st_diag*iter, N_st_diag, sze, & - 1.d0, U, size(U,1), W(1,1,iter), size(W,1), & - 0.d0, h(1,1,1,iter), size(h,1)*size(h,2)) + call dgemm('T','N', shift2, N_st_diag, sze, & + 1.d0, U, size(U,1), W(1,shift+1), size(W,1), & + 0.d0, h(1,shift+1), size(h,1)) + + call dgemm('T','N', shift2, N_st_diag, sze, & + 1.d0, U, size(U,1), S(1,shift+1), size(S,1), & + 0.d0, s_(1,shift+1), size(s_,1)) ! Diagonalize h ! ------------- - call lapack_diag(lambda,y,h,N_st_diag*davidson_sze_max,N_st_diag*iter) + call lapack_diag(lambda,y,h,size(h,1),shift2) + ! Compute S2 for each eigenvector + ! ------------------------------- + + call dgemm('N','N',shift2,shift2,shift2, & + 1.d0, s_, size(s_,1), y, size(y,1), & + 0.d0, s_tmp, size(s_tmp,1)) + + call dgemm('T','N',shift2,shift2,shift2, & + 1.d0, y, size(y,1), s_tmp, size(s_tmp,1), & + 0.d0, s_, size(s_,1)) + + do k=1,shift2 + s2(k) = s_(k,k) + S_z2_Sz + enddo + + if (s2_eig) then + logical :: state_ok(N_st_diag*davidson_sze_max) + do k=1,shift2 + state_ok(k) = (dabs(s2(k)-expected_s2) < 0.3d0) + enddo + do k=1,shift2 + if (.not. state_ok(k)) then + do l=k+1,shift2 + if (state_ok(l)) then + call dswap(shift2, y(1,k), 1, y(1,l), 1) + call dswap(1, s2(k), 1, s2(l), 1) + call dswap(1, lambda(k), 1, lambda(l), 1) + state_ok(k) = .True. + state_ok(l) = .False. + exit + endif + enddo + endif + enddo + endif + + ! Express eigenvectors of h in the determinant basis ! -------------------------------------------------- - do k=1,N_st_diag - do i=1,sze - U(i,k,iter+1) = 0.d0 - W(i,k,iter+1) = 0.d0 - S(i,k,iter+1) = 0.d0 - enddo - enddo - ! do k=1,N_st_diag -! do iter2=1,iter -! do l=1,N_st_diag -! do i=1,sze -! 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) -! S(i,k,iter+1) = W(i,k,iter+1) + S(i,l,iter2)*y(l,iter2,k,1) -! enddo +! do i=1,sze +! U(i,shift2+k) = 0.d0 +! W(i,shift2+k) = 0.d0 +! S(i,shift2+k) = 0.d0 +! enddo +! do l=1,N_st_diag*iter +! do i=1,sze +! U(i,shift2+k) = U(i,shift2+k) + U(i,l)*y(l,k) +! W(i,shift2+k) = W(i,shift2+k) + W(i,l)*y(l,k) +! S(i,shift2+k) = S(i,shift2+k) + S(i,l)*y(l,k) ! enddo ! enddo ! enddo ! ! - call dgemm('N','N', sze, N_st_diag, N_st_diag*iter, & - 1.d0, U, size(U,1), y, size(y,1)*size(y,2), 0.d0, U(1,1,iter+1), size(U,1)) - call dgemm('N','N',sze,N_st_diag,N_st_diag*iter, & - 1.d0, W, size(W,1), y, size(y,1)*size(y,2), 0.d0, W(1,1,iter+1), size(W,1)) - call dgemm('N','N',sze,N_st_diag,1, & - 1.d0, S, size(S,1), y, size(y,1)*size(y,2), 0.d0, S(1,1,iter+1), size(S,1)) + call dgemm('N','N', sze, N_st_diag, shift2, & + 1.d0, U, size(U,1), y, size(y,1), 0.d0, U(1,shift2+1), size(U,1)) + call dgemm('N','N', sze, N_st_diag, shift2, & + 1.d0, W, size(W,1), y, size(y,1), 0.d0, W(1,shift2+1), size(W,1)) + call dgemm('N','N', sze, N_st_diag, shift2, & + 1.d0, S, size(S,1), y, size(y,1), 0.d0, S(1,shift2+1), size(S,1)) ! Compute residual vector ! ----------------------- - do k=1,N_st_diag - s2(k) = u_dot_v(U(1,k,iter+1), S(1,k,iter+1), sze) + S_z2_Sz - enddo - +! do k=1,N_st_diag +! print *, s2(k) +! s2(k) = u_dot_v(U(1,shift2+k), S(1,shift2+k), sze) + S_z2_Sz +! print *, s2(k) +! print *, '' +! pause +! enddo do k=1,N_st_diag do i=1,sze - R(i,k) = (lambda(k) * U(i,k,iter+1) - W(i,k,iter+1) ) & - * (1.d0 + s2(k) * U(i,k,iter+1) - S(i,k,iter+1) - S_z2_Sz) + R(i,k) = (lambda(k) * U(i,shift2+k) - W(i,shift2+k) ) & + * (1.d0 + s2(k) * U(i,shift2+k) - S(i,shift2+k) - S_z2_Sz) enddo if (k <= N_st) then residual_norm(k) = u_dot_u(R(1,k),sze) @@ -305,7 +351,7 @@ subroutine davidson_diag_hjj_sjj(dets_in,u_in,H_jj,S2_jj,energies,dim_in,sze,N_s do k=1,N_st_diag do i=1,sze - U(i,k,iter+1) = - R(i,k)/max(H_jj(i) - lambda(k),1.d-2) + U(i,shift2+k) = - R(i,k)/max(H_jj(i) - lambda(k),1.d-2) enddo enddo @@ -314,33 +360,31 @@ subroutine davidson_diag_hjj_sjj(dets_in,u_in,H_jj,S2_jj,energies,dim_in,sze,N_s do k=1,N_st_diag -! do iter2=1,iter -! do l=1,N_st_diag -! c(1) = u_dot_v(U(1,k,iter+1),U(1,l,iter2),sze) +! do l=1,N_st_diag*iter +! c(1) = u_dot_v(U(1,shift2+k),U(1,l),sze) ! do i=1,sze -! U(i,k,iter+1) = U(i,k,iter+1) - c(1) * U(i,l,iter2) +! U(i,k,iter+1) = U(i,shift2+k) - c(1) * U(i,l) ! enddo -! enddo ! enddo ! call dgemv('T',sze,N_st_diag*iter,1.d0,U,size(U,1), & - U(1,k,iter+1),1,0.d0,c,1) + U(1,shift2+k),1,0.d0,c,1) call dgemv('N',sze,N_st_diag*iter,-1.d0,U,size(U,1), & - c,1,1.d0,U(1,k,iter+1),1) + c,1,1.d0,U(1,shift2+k),1) ! ! do l=1,k-1 -! c(1) = u_dot_v(U(1,k,iter+1),U(1,l,iter+1),sze) +! c(1) = u_dot_v(U(1,shift2+k),U(1,shift2+l),sze) ! do i=1,sze -! U(i,k,iter+1) = U(i,k,iter+1) - c(1) * U(i,l,iter+1) +! U(i,k,iter+1) = U(i,shift2+k) - c(1) * U(i,shift2+l) ! enddo ! enddo ! - call dgemv('T',sze,k-1,1.d0,U(1,1,iter+1),size(U,1), & - U(1,k,iter+1),1,0.d0,c,1) - call dgemv('N',sze,k-1,-1.d0,U(1,1,iter+1),size(U,1), & - c,1,1.d0,U(1,k,iter+1),1) + call dgemv('T',sze,k-1,1.d0,U(1,shift2+1),size(U,1), & + U(1,shift2+k),1,0.d0,c,1) + call dgemv('N',sze,k-1,-1.d0,U(1,shift2+1),size(U,1), & + c,1,1.d0,U(1,shift2+k),1) - call normalize( U(1,k,iter+1), sze ) + call normalize( U(1,shift2+k), sze ) enddo enddo @@ -354,23 +398,19 @@ subroutine davidson_diag_hjj_sjj(dets_in,u_in,H_jj,S2_jj,energies,dim_in,sze,N_s do k=1,N_st_diag energies(k) = lambda(k) - do i=1,sze - u_in(i,k) = 0.d0 - enddo enddo + ! do k=1,N_st_diag ! do i=1,sze -! do iter2=1,iter -! do l=1,N_st_diag -! u_in(i,k) += U(i,l,iter2)*y(l,iter2,k,1) +! do l=1,iter*N_st_diag +! u_in(i,k) += U(i,l)*y(l,k) ! enddo ! enddo ! enddo ! enddo call dgemm('N','N', sze, N_st_diag, N_st_diag*iter, 1.d0, & - U, size(U,1), y, N_st_diag*davidson_sze_max, & - 0.d0, u_in, size(u_in,1)) + U, size(U,1), y, size(y,1), 0.d0, u_in, size(u_in,1)) enddo @@ -386,9 +426,9 @@ subroutine davidson_diag_hjj_sjj(dets_in,u_in,H_jj,S2_jj,energies,dim_in,sze,N_s kl_pairs, & W, residual_norm, & U, overlap, & - R, c, & + R, c, S, & h, & - y, & + y, s_, s_tmp, & lambda & ) end diff --git a/src/Davidson/diagonalize_CI.irp.f b/src/Davidson/diagonalize_CI.irp.f index 57bee09d..ecd2d6b2 100644 --- a/src/Davidson/diagonalize_CI.irp.f +++ b/src/Davidson/diagonalize_CI.irp.f @@ -55,6 +55,10 @@ END_PROVIDER if (diag_algorithm == "Davidson") then +! call davidson_diag(psi_det,CI_eigenvectors,CI_electronic_energy, & +! size(CI_eigenvectors,1), & +! N_det,min(N_det,N_states),min(N_det,N_states_diag),N_int,output_determinants) +! call davidson_diag_HS2(psi_det,CI_eigenvectors, & size(CI_eigenvectors,1),CI_electronic_energy, & N_det,min(N_det,N_states),min(N_det,N_states_diag),N_int,output_determinants) @@ -145,71 +149,6 @@ END_PROVIDER deallocate(eigenvectors,eigenvalues) endif - - if( s2_eig.and.(N_states_diag > 1).and.(N_det >= N_states_diag) )then - ! Diagonalizing S^2 within the "n_states_diag" states found - allocate(s2_eigvalues(N_states_diag), e_array(N_states_diag)) - call diagonalize_s2_betweenstates(psi_det,CI_eigenvectors,N_det,size(psi_det,3), & - size(CI_eigenvectors,1),min(n_states_diag,n_det),s2_eigvalues) - - double precision, allocatable :: psi_coef_tmp(:,:) - allocate(psi_coef_tmp(psi_det_size,N_states_diag)) - do j = 1, N_states_diag - do i = 1, N_det - psi_coef_tmp(i,j) = CI_eigenvectors(i,j) - enddo - enddo - call u_0_H_u_0(e_array,psi_coef_tmp,n_det,psi_det,N_int,N_states_diag,psi_det_size) - - ! Browsing the "n_states_diag" states and getting the lowest in energy "n_states" ones that have the S^2 value - ! closer to the "expected_s2" set as input - - allocate(index_good_state_array(N_det),good_state_array(N_det)) - good_state_array = .False. - i_state = 0 - do j = 1, N_states_diag - if(dabs(s2_eigvalues(j)-expected_s2).le.0.5d0)then - good_state_array(j) = .True. - i_state +=1 - index_good_state_array(i_state) = j - endif - enddo - ! Sorting the i_state good states by energy - allocate(iorder(i_state)) - do j = 1, i_state - do i = 1, N_det - CI_eigenvectors(i,j) = psi_coef_tmp(i,index_good_state_array(j)) - enddo - CI_eigenvectors_s2(j) = s2_eigvalues(index_good_state_array(j)) - CI_electronic_energy(j) = e_array(j) - iorder(j) = j - enddo - call dsort(e_array,iorder,i_state) - do j = 1, i_state - CI_electronic_energy(j) = e_array(j) - CI_eigenvectors_s2(j) = s2_eigvalues(index_good_state_array(iorder(j))) - do i = 1, N_det - CI_eigenvectors(i,j) = psi_coef_tmp(i,index_good_state_array(iorder(j))) - enddo - enddo - - ! Then setting the other states without any specific energy order - i_other_state = 0 - do j = 1, N_states_diag - if(good_state_array(j))cycle - i_other_state +=1 - do i = 1, N_det - CI_eigenvectors(i,i_state + i_other_state) = psi_coef_tmp(i,j) - enddo - CI_eigenvectors_s2(i_state + i_other_state) = s2_eigvalues(j) - CI_electronic_energy(i_state + i_other_state) = e_array(i_state + i_other_state) - enddo - deallocate(iorder,e_array,index_good_state_array,good_state_array,psi_coef_tmp) - - deallocate(s2_eigvalues) - - endif - END_PROVIDER subroutine diagonalize_CI