return_perturbed_ground_spec Subroutine

public subroutine return_perturbed_ground_spec(perturbs, ilut_list, pert_ground_local, all_norm_pert)

Arguments

Type IntentOptional Attributes Name
type(perturbation), intent(in), allocatable :: perturbs(:)
integer(kind=n_int), intent(in) :: ilut_list(:,:)
real(kind=dp), intent(inout) :: pert_ground_local(:)
real(kind=dp), intent(out) :: all_norm_pert

Contents


Source Code

    subroutine return_perturbed_ground_spec(perturbs, ilut_list, pert_ground_local, all_norm_pert)

        ! This routine takes a perturbation operator, the list of all
        ! possible determinants (ilut_list). It reads in a popsfile, applies
        ! the perturbation to the read in state, and then copies the amplitudes
        ! of this perturbed popsfile state to pert_ground_local, using an
        ! ordering and addressing defined by ilut_list. It all divides these
        ! amplitudes by the norm of the read in wave function *BEFORE* the
        ! perturbation is applied (as needed for spectral calculations) and
        ! returns the norm of the perturbed popsfile as an output.

        use bit_rep_data, only: nifd, extract_sign
        use bit_reps, only: decode_bit_det
        use DetBitOps, only: DetBitEq, EncodeBitDet, ilut_lt, ilut_gt
        use FciMCData, only: TotWalkers, CurrentDets
        use PopsfileMod, only: read_popsfile_wrapper
        use sort_mod, only: sort
        use SystemData, only: nel

        type(perturbation), intent(in), allocatable :: perturbs(:)
        integer(n_int), intent(in) :: ilut_list(:, :)
        real(dp), intent(inout) :: pert_ground_local(:)
        real(dp), intent(out) :: all_norm_pert

        integer :: i, j
        integer :: nI(nel)
        real(dp) :: real_sign(lenof_sign)
        real(dp) :: norm_pert
        character(len=*), parameter :: t_r = 'return_perturbed_ground_spec'

        pert_ground_local = 0.0_dp

        ! Read in the POPSFILE and apply the perturbation operator in perturbs,
        ! as we do so. Afterwards, the perturbed wave function will be stored in
        ! CurrentDets.
        call read_popsfile_wrapper(perturbs)

        j = 0
        norm_pert = 0.0_dp
        call sort(CurrentDets(:, 1:TotWalkers), ilut_lt, ilut_gt)
        do i = 1, int(TotWalkers)
            call extract_sign(CurrentDets(:, i), real_sign)
            ! If the POPSFILE was generated from a calculation with the linear-scaling
            ! algorithm then it is possible to have the same determinant twice in a
            ! row, once with zero weight. If this is the case, skip the second case.
            if (i > 1) then
                if (DetBitEq(CurrentDets(:, i - 1), CurrentDets(:, i), nifd)) cycle
            end if
            norm_pert = norm_pert + real_sign(1) * real_sign(1)
            do
                j = j + 1
                if (DetBitEq(CurrentDets(:, i), ilut_list(:, j), nifd)) then
                    pert_ground_local(j) = real_sign(1)
                    exit
                end if
            end do
        end do

        ! The contributions to pops_norm are added in as the determinants are
        ! read in from the popsfile, which is only done on the root process, so
        ! brooadcast the value to other processors.
        call MPIBCast(pops_norm)
        pert_ground_local = pert_ground_local / sqrt(pops_norm)

        call MPISumAll(norm_pert, all_norm_pert)
        all_norm_pert = sqrt(all_norm_pert)

    end subroutine return_perturbed_ground_spec