Bottom-up computation of n-body dipole correction Exactly mirrors the energy MBE logic: deltaDipole = Dipole - sum(all subset deltaDipoles) Dipoles are additive vectors in the system frame, no coordinate mapping needed
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer(kind=int64), | intent(in) | :: | fragment_idx | |||
| integer, | intent(in) | :: | fragment(:) | |||
| type(fragment_lookup_t), | intent(in) | :: | lookup | |||
| type(calculation_result_t), | intent(in) | :: | results(:) | |||
| real(kind=dp), | intent(inout) | :: | delta_dipoles(:,:) |
(3, fragment_count) |
||
| integer, | intent(in) | :: | n | |||
| type(comm_t), | intent(in), | optional | :: | world_comm |
MPI communicator for abort |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| logical, | private | :: | has_next | ||||
| integer, | private | :: | i | ||||
| integer, | private | :: | indices(MAX_MBE_LEVEL) | ||||
| integer, | private | :: | subset(MAX_MBE_LEVEL) | ||||
| integer(kind=int64), | private | :: | subset_idx | ||||
| integer, | private | :: | subset_size |
subroutine compute_mbe_dipole(fragment_idx, fragment, lookup, results, delta_dipoles, n, world_comm) !! Bottom-up computation of n-body dipole correction !! Exactly mirrors the energy MBE logic: deltaDipole = Dipole - sum(all subset deltaDipoles) !! Dipoles are additive vectors in the system frame, no coordinate mapping needed use mqc_result_types, only: calculation_result_t integer(int64), intent(in) :: fragment_idx integer, intent(in) :: fragment(:), n type(fragment_lookup_t), intent(in) :: lookup type(calculation_result_t), intent(in) :: results(:) real(dp), intent(inout) :: delta_dipoles(:, :) !! (3, fragment_count) type(comm_t), intent(in), optional :: world_comm !! MPI communicator for abort integer :: subset_size, i integer :: indices(MAX_MBE_LEVEL), subset(MAX_MBE_LEVEL) ! Stack arrays to avoid heap contention integer(int64) :: subset_idx logical :: has_next ! Start with the full n-mer dipole delta_dipoles(:, fragment_idx) = results(fragment_idx)%dipole ! Subtract all proper subsets (size 1 to n-1) do subset_size = 1, n - 1 ! Initialize first combination do i = 1, subset_size indices(i) = i end do ! Loop through all combinations do ! Build current subset do i = 1, subset_size subset(i) = fragment(indices(i)) end do ! Look up subset index subset_idx = lookup%find(subset(1:subset_size), subset_size) if (subset_idx < 0) then call logger%error("Subset not found in MBE dipole computation") if (present(world_comm)) then call abort_comm(world_comm, 1) else error stop "Subset not found in MBE dipole!" end if end if ! Subtract pre-computed delta dipole delta_dipoles(:, fragment_idx) = delta_dipoles(:, fragment_idx) - & delta_dipoles(:, subset_idx) ! Get next combination call get_next_combination(indices, subset_size, n, has_next) if (.not. has_next) exit end do end do end subroutine compute_mbe_dipole