subroutine subspace_extraction_sl()
integer :: lwork, info, i
real(dp), allocatable :: work(:), left_pert_overlaps(:), left_pert_overlaps_all(:)
! Scrap space for the diagonaliser.
lwork = max(1, 3 * n_lanc_vecs_sl - 1)
allocate(work(lwork))
! This routine diagonalises a symmetric matrix, A.
! V tells the routine to calculate eigenvalues *and* eigenvectors.
! U tells the routine to get the upper half of A (it is symmetric).
! n_lanc_vecs_sl is the number of rows and columns in A.
! A = sl_hamil. This matrix stores the eigenvectors in its columns on output.
! n_lanc_vecs_sl is the leading dimension of A.
! sl_h_eigv stores the eigenvalues on output.
! work is scrap space.
! lwork is the length of the work array.
! info = 0 on output if diagonalisation is successful.
call dsyev('V', 'U', n_lanc_vecs_sl, sl_hamil, n_lanc_vecs_sl, sl_h_eigv, work, lwork, info)
deallocate(work)
! The first Lanczos vector differs from the perturbed ground state only
! by a normalisation factor, which is accounted for here.
trans_amps_right = sl_hamil(1, :) * right_pert_norm / sqrt(pops_norm)
! Calculate the overlaps between the left-perturbed ground state and all
! of the Lanczos vectors.
allocate(left_pert_overlaps(n_lanc_vecs_sl))
allocate(left_pert_overlaps_all(n_lanc_vecs_sl))
left_pert_overlaps = matmul(pert_ground_left, sl_vecs)
! Sum the contributions to the overlaps from all processes.
call MPISumAll(left_pert_overlaps, left_pert_overlaps_all)
! And then use these overlaps to calculate the overlaps of the
! left-perturbed ground state with the final eigenvectors.
trans_amps_left = matmul(left_pert_overlaps_all, sl_hamil)
deallocate(left_pert_overlaps)
deallocate(left_pert_overlaps_all)
end subroutine subspace_extraction_sl