subroutine remove_high_energy_orbs(ilut_list, num_states, target_num_states, tParallel)
use Parallel_neci, only: MPISumAll
use sort_mod, only: sort
use SystemData, only: nBasis, BRR, Arr
integer, intent(inout) :: num_states
integer(n_int), intent(inout) :: ilut_list(0:NIfTot, 1:num_states)
integer, intent(in) :: target_num_states
logical, intent(in) :: tParallel
integer, allocatable, dimension(:) :: orbitals_rmvd
integer :: i, j, orb, num_orbs_rmvd
integer :: bit, elem
integer :: states_rmvd_this_proc, counter
integer(MPIArg) :: tot_num_states, states_rmvd_all_procs
logical :: occupied
states_rmvd_this_proc = 0
num_orbs_rmvd = 0
if (tParallel) then
call MPISumAll(int(num_states, MPIArg), tot_num_states)
else
tot_num_states = int(num_states, MPIArg)
end if
if (tot_num_states <= target_num_states) return
write(stdout, '(a32)') "Removing high energy orbitals..."
! Loop through all orbitals, from highest energy to lowest.
do i = nBasis, 1, -1
num_orbs_rmvd = nBasis - i + 1
orb = BRR(i)
bit = mod(orb - 1, bits_n_int)
elem = (orb - 1 - bit) / bits_n_int
! Loop through all states and remove those states with orbital orb
! occupied.
do j = 1, num_states
occupied = btest(ilut_list(elem, j), bit)
if (occupied) then
ilut_list(:, j) = 0_n_int
states_rmvd_this_proc = states_rmvd_this_proc + 1
end if
end do
if (tParallel) then
call MPISumAll(int(states_rmvd_this_proc, MPIArg), states_rmvd_all_procs)
else
states_rmvd_all_procs = int(states_rmvd_this_proc, MPIArg)
end if
! If there are degenerate orbitals, then cycle to remove the
! degenerate orbitals too, before giving the program chance to quit.
if (i > 1) then
! If the orbitals energies are the same:
if (abs(Arr(i, 1) - Arr((i - 1), 1)) < 1.0e-12_dp) cycle
end if
if (tot_num_states - states_rmvd_all_procs <= target_num_states) exit
end do
! Loop through the list and shuffle states down to fill in the gaps
! created above.
counter = 0
do i = 1, num_states
! If the state wasn't set to 0:
if (.not. all(ilut_list(:, i) == 0_n_int)) then
counter = counter + 1
ilut_list(:, counter) = ilut_list(:, i)
end if
end do
if (counter /= num_states - states_rmvd_this_proc) &
call stop_all("remove_high_energy_orbs", &
"Wrong number of states found.")
num_states = counter
! Finally, output information:
write(stdout, '(a36)', advance='no') "The following orbitals were removed:"
allocate(orbitals_rmvd(num_orbs_rmvd))
orbitals_rmvd = BRR(nBasis - num_orbs_rmvd + 1:nBasis)
call sort(orbitals_rmvd)
do i = 1, num_orbs_rmvd
write(stdout, '(i5)', advance='no') orbitals_rmvd(i)
if (i == num_orbs_rmvd) write(stdout, '()', advance='yes')
end do
deallocate(orbitals_rmvd)
write(stdout, '(i6,1x,a29)') states_rmvd_all_procs, "states were removed in total."
write(stdout, '(i6,1x,a17)') tot_num_states - states_rmvd_all_procs, "states were kept."
call neci_flush(stdout)
end subroutine remove_high_energy_orbs