Redistribute hydrogen cap gradients to original atoms
This subroutine handles gradient redistribution for fragments with hydrogen caps. Hydrogen caps are virtual atoms added at broken bonds - their gradients represent forces at the bond breakpoint and must be transferred to the original atoms they replace.
Algorithm: 1. For real atoms (indices 1 to n_atoms - n_caps): Accumulate gradient to system using local_to_global mapping 2. For hydrogen caps (indices n_atoms - n_caps + 1 to n_atoms): Add cap gradient to the original atom it replaces (from cap_replaces_atom)
Example: Fragment: [C, C, H_cap] where H_cap replaces atom 5 in system Fragment gradient: [(3,1), (3,2), (3,3)] - Atoms 1,2: accumulate to system using local_to_global - Atom 3 (cap): add gradient to system atom 5 (cap_replaces_atom(1) + 1)
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(physical_fragment_t), | intent(in) | :: | fragment | |||
| real(kind=dp), | intent(in) | :: | fragment_gradient(:,:) |
(3, n_atoms_fragment) |
||
| real(kind=dp), | intent(inout) | :: | system_gradient(:,:) |
(3, n_atoms_system) |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | global_idx | ||||
| integer, | private | :: | global_original_idx | ||||
| integer, | private | :: | i | ||||
| integer, | private | :: | i_cap | ||||
| integer, | private | :: | local_cap_idx | ||||
| integer, | private | :: | local_idx | ||||
| integer, | private | :: | n_real_atoms |
subroutine redistribute_cap_gradients(fragment, fragment_gradient, system_gradient) !! Redistribute hydrogen cap gradients to original atoms !! !! This subroutine handles gradient redistribution for fragments with hydrogen caps. !! Hydrogen caps are virtual atoms added at broken bonds - their gradients represent !! forces at the bond breakpoint and must be transferred to the original atoms they replace. !! !! Algorithm: !! 1. For real atoms (indices 1 to n_atoms - n_caps): !! Accumulate gradient to system using local_to_global mapping !! 2. For hydrogen caps (indices n_atoms - n_caps + 1 to n_atoms): !! Add cap gradient to the original atom it replaces (from cap_replaces_atom) !! !! Example: !! Fragment: [C, C, H_cap] where H_cap replaces atom 5 in system !! Fragment gradient: [(3,1), (3,2), (3,3)] !! - Atoms 1,2: accumulate to system using local_to_global !! - Atom 3 (cap): add gradient to system atom 5 (cap_replaces_atom(1) + 1) type(physical_fragment_t), intent(in) :: fragment real(dp), intent(in) :: fragment_gradient(:, :) !! (3, n_atoms_fragment) real(dp), intent(inout) :: system_gradient(:, :) !! (3, n_atoms_system) integer :: i, local_idx, global_idx integer :: i_cap, local_cap_idx, global_original_idx integer :: n_real_atoms n_real_atoms = fragment%n_atoms - fragment%n_caps ! Accumulate gradients for real atoms using local→global mapping do i = 1, n_real_atoms global_idx = fragment%local_to_global(i) system_gradient(:, global_idx) = system_gradient(:, global_idx) + fragment_gradient(:, i) end do ! Redistribute cap gradients to original atoms they replace if (fragment%n_caps > 0) then do i_cap = 1, fragment%n_caps local_cap_idx = n_real_atoms + i_cap ! cap_replaces_atom is 0-indexed, add 1 for Fortran arrays global_original_idx = fragment%cap_replaces_atom(i_cap) + 1 ! Add cap gradient to the atom it replaces system_gradient(:, global_original_idx) = system_gradient(:, global_original_idx) + & fragment_gradient(:, local_cap_idx) end do end if end subroutine redistribute_cap_gradients