calculate_monomer_distance Function

public pure function calculate_monomer_distance(sys_geom, monomer_indices) result(min_distance)

Calculate minimal atomic distance between monomers in a fragment For single monomer (size 1), returns 0.0 For multi-monomer fragments, returns minimal distance between atoms in different monomers Result is in Angstrom

Arguments

Type IntentOptional Attributes Name
type(system_geometry_t), intent(in) :: sys_geom
integer, intent(in) :: monomer_indices(:)

Return Value real(kind=dp)


Calls

proc~~calculate_monomer_distance~~CallsGraph proc~calculate_monomer_distance calculate_monomer_distance proc~to_angstrom to_angstrom proc~calculate_monomer_distance->proc~to_angstrom

Called by

proc~~calculate_monomer_distance~~CalledByGraph proc~calculate_monomer_distance calculate_monomer_distance proc~build_fragment_from_indices build_fragment_from_indices proc~build_fragment_from_indices->proc~calculate_monomer_distance proc~fragment_should_be_screened fragment_should_be_screened proc~fragment_should_be_screened->proc~calculate_monomer_distance proc~apply_distance_screening apply_distance_screening proc~apply_distance_screening->proc~fragment_should_be_screened proc~compute_gmbe compute_gmbe proc~compute_gmbe->proc~build_fragment_from_indices proc~map_fragment_to_system_dipole_derivatives map_fragment_to_system_dipole_derivatives proc~map_fragment_to_system_dipole_derivatives->proc~build_fragment_from_indices proc~map_fragment_to_system_gradient map_fragment_to_system_gradient proc~map_fragment_to_system_gradient->proc~build_fragment_from_indices proc~map_fragment_to_system_hessian map_fragment_to_system_hessian proc~map_fragment_to_system_hessian->proc~build_fragment_from_indices proc~node_worker node_worker proc~node_worker->proc~build_fragment_from_indices proc~serial_fragment_processor serial_fragment_processor proc~serial_fragment_processor->proc~build_fragment_from_indices proc~compute_mbe compute_mbe proc~serial_fragment_processor->proc~compute_mbe interface~node_worker node_worker interface~node_worker->proc~node_worker interface~serial_fragment_processor serial_fragment_processor interface~serial_fragment_processor->proc~serial_fragment_processor proc~compute_mbe->proc~map_fragment_to_system_dipole_derivatives proc~compute_mbe->proc~map_fragment_to_system_gradient proc~compute_mbe->proc~map_fragment_to_system_hessian proc~compute_mbe_dipole_derivatives compute_mbe_dipole_derivatives proc~compute_mbe->proc~compute_mbe_dipole_derivatives proc~compute_mbe_gradient compute_mbe_gradient proc~compute_mbe->proc~compute_mbe_gradient proc~compute_mbe_hessian compute_mbe_hessian proc~compute_mbe->proc~compute_mbe_hessian proc~compute_mbe_dipole_derivatives->proc~map_fragment_to_system_dipole_derivatives proc~compute_mbe_gradient->proc~map_fragment_to_system_gradient proc~compute_mbe_hessian->proc~map_fragment_to_system_hessian proc~run_fragmented_calculation run_fragmented_calculation proc~run_fragmented_calculation->proc~apply_distance_screening proc~global_coordinator global_coordinator proc~global_coordinator->proc~compute_mbe proc~gmbe_run_distributed gmbe_context_t%gmbe_run_distributed proc~gmbe_run_distributed->interface~node_worker proc~mbe_run_distributed mbe_context_t%mbe_run_distributed proc~mbe_run_distributed->interface~node_worker proc~mbe_run_serial mbe_context_t%mbe_run_serial proc~mbe_run_serial->interface~serial_fragment_processor proc~run_calculation run_calculation proc~run_calculation->proc~run_fragmented_calculation interface~global_coordinator global_coordinator interface~global_coordinator->proc~global_coordinator proc~compute_energy_and_forces compute_energy_and_forces proc~compute_energy_and_forces->proc~run_calculation proc~run_multi_molecule_calculations run_multi_molecule_calculations proc~run_multi_molecule_calculations->proc~run_calculation program~main main program~main->proc~run_calculation

Variables

Type Visibility Attributes Name Initial
integer, private :: atom_end_i
integer, private :: atom_end_j
integer, private :: atom_start_i
integer, private :: atom_start_j
real(kind=dp), private :: dist
real(kind=dp), private :: dx
real(kind=dp), private :: dy
real(kind=dp), private :: dz
integer, private :: i
integer, private :: iatom
logical, private :: is_variable_size
integer, private :: j
integer, private :: jatom
integer, private :: mon_i
integer, private :: mon_j
integer, private :: n_monomers

Source Code

   pure function calculate_monomer_distance(sys_geom, monomer_indices) result(min_distance)
      !! Calculate minimal atomic distance between monomers in a fragment
      !! For single monomer (size 1), returns 0.0
      !! For multi-monomer fragments, returns minimal distance between atoms in different monomers
      !! Result is in Angstrom
      type(system_geometry_t), intent(in) :: sys_geom
      integer, intent(in) :: monomer_indices(:)
      real(dp) :: min_distance

      integer :: n_monomers, i, j, iatom, jatom
      integer :: mon_i, mon_j
      integer :: atom_start_i, atom_end_i, atom_start_j, atom_end_j
      real(dp) :: dist, dx, dy, dz
      logical :: is_variable_size

      n_monomers = size(monomer_indices)

      ! Monomers have distance 0
      if (n_monomers == 1) then
         min_distance = 0.0_dp
         return
      end if

      ! Check if we have variable-sized fragments
      is_variable_size = allocated(sys_geom%fragment_sizes)

      ! Initialize with huge value
      min_distance = huge(1.0_dp)

      ! Loop over all pairs of monomers
      do i = 1, n_monomers - 1
         mon_i = monomer_indices(i)
         do j = i + 1, n_monomers
            mon_j = monomer_indices(j)

            if (is_variable_size) then
               ! Variable-sized fragments
               do iatom = 1, sys_geom%fragment_sizes(mon_i)
                  atom_start_i = sys_geom%fragment_atoms(iatom, mon_i) + 1  ! Convert to 1-indexed
                  do jatom = 1, sys_geom%fragment_sizes(mon_j)
                     atom_start_j = sys_geom%fragment_atoms(jatom, mon_j) + 1  ! Convert to 1-indexed

                     ! Calculate distance (coordinates in Bohr)
                     dx = sys_geom%coordinates(1, atom_start_i) - sys_geom%coordinates(1, atom_start_j)
                     dy = sys_geom%coordinates(2, atom_start_i) - sys_geom%coordinates(2, atom_start_j)
                     dz = sys_geom%coordinates(3, atom_start_i) - sys_geom%coordinates(3, atom_start_j)
                     dist = sqrt(dx*dx + dy*dy + dz*dz)

                     if (dist < min_distance) min_distance = dist
                  end do
               end do
            else
               ! Fixed-sized monomers
               atom_start_i = (mon_i - 1)*sys_geom%atoms_per_monomer + 1
               atom_end_i = mon_i*sys_geom%atoms_per_monomer

               atom_start_j = (mon_j - 1)*sys_geom%atoms_per_monomer + 1
               atom_end_j = mon_j*sys_geom%atoms_per_monomer

               ! Loop over all atom pairs
               do iatom = atom_start_i, atom_end_i
                  do jatom = atom_start_j, atom_end_j
                     ! Calculate distance (coordinates in Bohr)
                     dx = sys_geom%coordinates(1, iatom) - sys_geom%coordinates(1, jatom)
                     dy = sys_geom%coordinates(2, iatom) - sys_geom%coordinates(2, jatom)
                     dz = sys_geom%coordinates(3, iatom) - sys_geom%coordinates(3, jatom)
                     dist = sqrt(dx*dx + dy*dy + dz*dz)

                     if (dist < min_distance) min_distance = dist
                  end do
               end do
            end if
         end do
      end do

      ! Convert from Bohr to Angstrom
      min_distance = to_angstrom(min_distance)

   end function calculate_monomer_distance