get_partitioned_coordination_number Subroutine

public subroutine get_partitioned_coordination_number(mol, trans, cutoff, rcov, cn, partition)

Geometric fractional coordination number with a partitioned pair loop.

The counting function is reproduced here rather than taken from mctc-lib, which offers no way to restrict the pairs it evaluates. The unit tests check that both agree.

Arguments

Type IntentOptional Attributes Name
type(structure_type), intent(in) :: mol

Molecular structure data

real(kind=wp), intent(in) :: trans(:,:)

Lattice points

real(kind=wp), intent(in) :: cutoff

Real space cutoff

real(kind=wp), intent(in) :: rcov(:)

Covalent radius

real(kind=wp), intent(out) :: cn(:)

Error function coordination number.

type(work_partition), intent(in), optional :: partition

Work partition of the pair loop, absent selects the complete work


Source Code

subroutine get_partitioned_coordination_number(mol, trans, cutoff, rcov, cn, partition)

   !> Molecular structure data
   type(structure_type), intent(in) :: mol

   !> Lattice points
   real(wp), intent(in) :: trans(:, :)

   !> Real space cutoff
   real(wp), intent(in) :: cutoff

   !> Covalent radius
   real(wp), intent(in) :: rcov(:)

   !> Error function coordination number.
   real(wp), intent(out) :: cn(:)

   !> Work partition of the pair loop, absent selects the complete work
   type(work_partition), intent(in), optional :: partition

   integer :: iat, jat, izp, jzp, itr
   real(wp) :: vec(3), r2, r1, rc, cutoff2, countf
   real(wp), allocatable :: cn_local(:)

   cn(:) = 0.0_wp
   cutoff2 = cutoff*cutoff

   !$omp parallel default(none) &
   !$omp shared(mol, trans, cutoff2, rcov, cn, partition) &
   !$omp private(iat, jat, itr, izp, jzp, vec, r2, r1, rc, countf, cn_local)
   allocate(cn_local(size(cn)), source=0.0_wp)
   !$omp do schedule(runtime)
   do iat = 1, mol%nat
      izp = mol%id(iat)
      do jat = 1, iat
         if (.not.owns_pair(partition, iat, jat)) cycle
         jzp = mol%id(jat)
         rc = rcov(izp) + rcov(jzp)
         do itr = 1, size(trans, 2)
            vec(:) = mol%xyz(:, iat) - (mol%xyz(:, jat) + trans(:, itr))
            r2 = vec(1)*vec(1) + vec(2)*vec(2) + vec(3)*vec(3)
            if (r2 > cutoff2 .or. r2 < 1.0e-12_wp) cycle
            r1 = sqrt(r2)

            countf = 1.0_wp/(1.0_wp + exp(-default_kcn*(rc/r1 - 1.0_wp)))

            cn_local(iat) = cn_local(iat) + countf
            if (iat /= jat) cn_local(jat) = cn_local(jat) + countf
         end do
      end do
   end do
   !$omp end do
   !$omp critical (get_partitioned_coordination_number_)
   cn(:) = cn(:) + cn_local(:)
   !$omp end critical (get_partitioned_coordination_number_)
   deallocate(cn_local)
   !$omp end parallel

end subroutine get_partitioned_coordination_number