init_spectral_lanczos Subroutine

public subroutine init_spectral_lanczos()

Arguments

None

Contents

Source Code


Source Code

    subroutine init_spectral_lanczos()

        use bit_rep_data, only: nifd, extract_sign
        use DetBitOps, only: DetBitEq, EncodeBitDet, ilut_lt, ilut_gt
        use gndts_mod, only: gndts
        use load_balance_calcnodes, only: DetermineDetNode
        use sort_mod, only: sort
        use SystemData, only: nbasis, nel, BRR, nBasisMax, G1, tSpn, LMS, tParity, SymRestrict

        integer :: ndets_this_proc, ndets_tot
        integer(MPIArg) :: mpi_temp
        integer, allocatable :: nI_list(:, :)

        integer(n_int) :: ilut(0:NIfTot)
        character(len=*), parameter :: t_r = 'init_spectral_lanczos'
        integer :: i, j, ndets, proc, ierr, temp(1, 1), hf_ind
        real(dp) :: real_sign(lenof_sign)
        real(dp) :: norm_pert

        write(stdout, '(/,1x,a39,/)') "Beginning spectral Lanczos calculation."
        call neci_flush(stdout)

        allocate(ndets_sl(0:nProcessors - 1))
        allocate(disps_sl(0:nProcessors - 1))

        write(stdout, '(1x,a56)', advance='yes') "Enumerating and storing all determinants in the space..."
        call neci_flush(stdout)

        ! Determine the total number of determinants.
        call gndts(nel, nbasis, BRR, nBasisMax, temp, .true., G1, tSpn, lms, tParity, SymRestrict, ndets, hf_ind)
        allocate(nI_list(nel, ndets))
        ! Now generate them again and store them this time.
        call gndts(nel, nbasis, BRR, nBasisMax, nI_list, .false., G1, tSpn, lms, tParity, SymRestrict, ndets, hf_ind)

        ! Count the number of determinants belonging to this processor.
        ndets_this_proc = 0
        do i = 1, ndets
            proc = DetermineDetNode(nel, nI_list(:, i), 0)
            if (proc == iProcIndex) ndets_this_proc = ndets_this_proc + 1
        end do

        allocate(sl_ilut_list(0:NIfTot, ndets_this_proc))
        sl_ilut_list = 0_n_int

        j = 0
        do i = 1, ndets
            proc = DetermineDetNode(nel, nI_list(:, i), 0)
            if (proc == iProcIndex) then
                call EncodeBitDet(nI_list(:, i), ilut)
                j = j + 1
                sl_ilut_list(0:nifd, j) = ilut(0:nifd)
            end if
        end do

        call sort(sl_ilut_list, ilut_lt, ilut_gt)

        write(stdout, '(1x,a9)') "Complete."
        call neci_flush(stdout)

        mpi_temp = int(ndets_this_proc, MPIArg)
        call MPIAllGather(mpi_temp, ndets_sl, ierr)

        disps_sl(0) = 0
        do i = 1, nProcessors - 1
            disps_sl(i) = disps_sl(i - 1) + ndets_sl(i - 1)
        end do

        ndets_tot = int(sum(ndets_sl))

        write(stdout, '(1x,a44)', advance='no') "Allocating arrays to hold Lanczos vectors..."
        call neci_flush(stdout)
        allocate(sl_vecs(ndets_this_proc, n_lanc_vecs_sl))
        sl_vecs = 0.0_dp
        allocate(full_vec_sl(ndets_tot))
        write(stdout, '(1x,a9)') "Complete."
        call neci_flush(stdout)

        allocate(pert_ground_left(ndets_this_proc), stat=ierr)
        if (ierr /= 0) then
            write(stdout, '(1x,a11,1x,i5)') "Error code:", ierr
            call stop_all(t_r, "Error allocating array to hold left perturbed ground state components.")
        end if

        allocate(sl_hamil(n_lanc_vecs_sl, n_lanc_vecs_sl))
        allocate(sl_h_eigv(n_lanc_vecs_sl))
        allocate(sl_overlaps(n_lanc_vecs_sl))
        allocate(trans_amps_left(n_lanc_vecs_sl))
        allocate(trans_amps_right(n_lanc_vecs_sl))
        sl_hamil = 0.0_dp
        sl_h_eigv = 0.0_dp
        sl_overlaps = 0.0_dp
        trans_amps_left = 0.0_dp
        trans_amps_right = 0.0_dp

        write(stdout, '(1x,a48)') "Allocating and calculating Hamiltonian matrix..."
        call neci_flush(stdout)
        call calculate_sparse_ham_par(ndets_sl, sl_ilut_list, .true.)
        write(stdout, '(1x,a48,/)') "Hamiltonian allocation and calculation complete."
        call neci_flush(stdout)

        call return_perturbed_ground_spec(left_perturb_spectral, sl_ilut_list, pert_ground_left, left_pert_norm)
        call return_perturbed_ground_spec(right_perturb_spectral, sl_ilut_list, sl_vecs(:, 1), right_pert_norm)

        ! Normalise the perturbed wave function, currently stored in sl_vecs(:,1),
        ! so that it can be used as the first lanczos vector.
        sl_vecs(:, 1) = sl_vecs(:, 1) * sqrt(pops_norm) / right_pert_norm

    end subroutine init_spectral_lanczos