Evaluate smooth weights for competing nearest Wigner-Seitz images
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(wignerseitz_cell), | intent(in) | :: | self |
Wigner-Seitz cell instance |
||
| integer, | intent(in) | :: | jat |
Index of examined atom in the Wigner-Seitz image arrays |
||
| integer, | intent(in) | :: | iat |
Index of reference atom in the Wigner-Seitz image arrays |
||
| real(kind=wp), | intent(in) | :: | rij(3) |
Cartesian pair vector |
||
| real(kind=wp), | intent(out) | :: | weight(:) |
Normalized image weights |
||
| real(kind=wp), | intent(out), | optional | :: | dwdr(:,:) |
Weight derivatives with respect to the pair vector |
|
| real(kind=wp), | intent(out), | optional | :: | dwdL(:,:,:) |
Weight derivatives with respect to strain |
subroutine get_wignerseitz_weights(self, jat, iat, rij, weight, dwdr, dwdL) !> Wigner-Seitz cell instance type(wignerseitz_cell), intent(in) :: self !> Index of reference atom in the Wigner-Seitz image arrays integer, intent(in) :: iat !> Index of examined atom in the Wigner-Seitz image arrays integer, intent(in) :: jat !> Cartesian pair vector real(wp), intent(in) :: rij(3) !> Normalized image weights real(wp), intent(out) :: weight(:) !> Weight derivatives with respect to the pair vector real(wp), intent(out), optional :: dwdr(:, :) !> Weight derivatives with respect to strain real(wp), intent(out), optional :: dwdL(:, :, :) integer :: img, idx, nimg, refidx real(wp) :: delta, dshape, sum_shape real(wp) :: vec(3), refvec(3), ddelta(3), sum_dr(3) real(wp) :: ddeltaL(3, 3), sum_dL(3, 3) weight(:) = 0.0_wp if (present(dwdr)) dwdr(:, :) = 0.0_wp if (present(dwdL)) dwdL(:, :, :) = 0.0_wp nimg = self%nimg(jat, iat) if (nimg == 0) return refidx = self%tridx(1, jat, iat) refvec = rij - self%trans(:, refidx) sum_shape = 0.0_wp do img = 1, nimg idx = self%tridx(img, jat, iat) vec = rij - self%trans(:, idx) delta = max(0.0_wp, dot_product(vec, vec) - dot_product(refvec, refvec)) weight(img) = smooth_image_weight(delta) sum_shape = sum_shape + weight(img) end do weight(:nimg) = weight(:nimg) / sum_shape if (.not.present(dwdr) .and. .not.present(dwdL)) return sum_dr(:) = 0.0_wp sum_dL(:, :) = 0.0_wp do img = 1, nimg idx = self%tridx(img, jat, iat) vec = rij - self%trans(:, idx) delta = max(0.0_wp, dot_product(vec, vec) - dot_product(refvec, refvec)) dshape = smooth_image_weight_derivative(delta) ddelta(:) = 2.0_wp*(vec - refvec) ddeltaL(:, :) = 2.0_wp*(spread(vec, 1, 3)*spread(vec, 2, 3) & & - spread(refvec, 1, 3)*spread(refvec, 2, 3)) sum_dr(:) = sum_dr + dshape*ddelta sum_dL(:, :) = sum_dL + dshape*ddeltaL end do do img = 1, nimg idx = self%tridx(img, jat, iat) vec = rij - self%trans(:, idx) delta = max(0.0_wp, dot_product(vec, vec) - dot_product(refvec, refvec)) dshape = smooth_image_weight_derivative(delta) ddelta(:) = 2.0_wp*(vec - refvec) ddeltaL(:, :) = 2.0_wp*(spread(vec, 1, 3)*spread(vec, 2, 3) & & - spread(refvec, 1, 3)*spread(refvec, 2, 3)) if (present(dwdr)) then dwdr(:, img) = (dshape*ddelta - weight(img)*sum_dr) / sum_shape end if if (present(dwdL)) then dwdL(:, :, img) = (dshape*ddeltaL - weight(img)*sum_dL) / sum_shape end if end do end subroutine get_wignerseitz_weights