Bottom-up computation of n-body Hessian correction Mirrors MBE gradient logic but for second derivatives Bond connectivity is accessed via sys_geom%bonds
| 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_hessians(:,:,:) |
(3total_atoms, 3total_atoms, fragment_count) |
||
| integer, | intent(in) | :: | n | |||
| type(system_geometry_t), | intent(in) | :: | sys_geom |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| logical, | private | :: | has_next | ||||
| integer, | private | :: | hess_dim | ||||
| 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_hessian(fragment_idx, fragment, lookup, results, delta_hessians, n, sys_geom) !! Bottom-up computation of n-body Hessian correction !! Mirrors MBE gradient logic but for second derivatives !! Bond connectivity is accessed via sys_geom%bonds use mqc_result_types, only: calculation_result_t use mqc_error, only: error_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_hessians(:, :, :) !! (3*total_atoms, 3*total_atoms, fragment_count) type(system_geometry_t), intent(in) :: sys_geom integer :: subset_size, i, hess_dim integer :: indices(MAX_MBE_LEVEL), subset(MAX_MBE_LEVEL) ! Stack arrays to avoid heap contention integer(int64) :: subset_idx logical :: has_next hess_dim = 3*sys_geom%total_atoms ! Start with the full n-mer Hessian mapped to system coordinates call map_fragment_to_system_hessian(results(fragment_idx)%hessian, fragment, & sys_geom, delta_hessians(:, :, fragment_idx)) ! 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 has_next = .true. do while (has_next) do i = 1, subset_size subset(i) = fragment(indices(i)) end do subset_idx = lookup%find(subset(1:subset_size), subset_size) if (subset_idx > 0) then ! Subtract this subset's delta Hessian delta_hessians(:, :, fragment_idx) = delta_hessians(:, :, fragment_idx) - & delta_hessians(:, :, subset_idx) end if call get_next_combination(indices, subset_size, n, has_next) end do end do end subroutine compute_mbe_hessian