Evaluation of the dispersion energy expression
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(rational_damping_param), | intent(in) | :: | self |
Damping parameters |
||
class(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) | :: | r4r2(:) |
Expectation values for r4 over r2 operator |
||
real(kind=wp), | intent(in) | :: | c6(:,:) |
C6 coefficients for all atom pairs. |
||
real(kind=wp), | intent(in) | :: | dc6dcn(:,:) |
Derivative of the C6 w.r.t. the coordination number |
||
real(kind=wp), | intent(in) | :: | dc6dq(:,:) |
Derivative of the C6 w.r.t. the partial charges |
||
real(kind=wp), | intent(inout) | :: | energy(:) |
Dispersion energy |
||
real(kind=wp), | intent(inout) | :: | dEdcn(:) |
Derivative of the energy w.r.t. the coordination number |
||
real(kind=wp), | intent(inout) | :: | dEdq(:) |
Derivative of the energy w.r.t. the partial charges |
||
real(kind=wp), | intent(inout) | :: | gradient(:,:) |
Dispersion gradient |
||
real(kind=wp), | intent(inout) | :: | sigma(:,:) |
Dispersion virial |
subroutine get_dispersion_derivs(self, mol, trans, cutoff, r4r2, c6, dc6dcn, dc6dq, & & energy, dEdcn, dEdq, gradient, sigma) !> Damping parameters class(rational_damping_param), intent(in) :: self !> Molecular structure data class(structure_type), intent(in) :: mol !> Lattice points real(wp), intent(in) :: trans(:, :) !> Real space cutoff real(wp), intent(in) :: cutoff !> Expectation values for r4 over r2 operator real(wp), intent(in) :: r4r2(:) !> C6 coefficients for all atom pairs. real(wp), intent(in) :: c6(:, :) !> Derivative of the C6 w.r.t. the coordination number real(wp), intent(in) :: dc6dcn(:, :) !> Derivative of the C6 w.r.t. the partial charges real(wp), intent(in) :: dc6dq(:, :) !> Dispersion energy real(wp), intent(inout) :: energy(:) !> Derivative of the energy w.r.t. the coordination number real(wp), intent(inout) :: dEdcn(:) !> Derivative of the energy w.r.t. the partial charges real(wp), intent(inout) :: dEdq(:) !> Dispersion gradient real(wp), intent(inout) :: gradient(:, :) !> Dispersion virial real(wp), intent(inout) :: sigma(:, :) integer :: iat, jat, izp, jzp, jtr real(wp) :: vec(3), r2, cutoff2, r0ij, rrij, c6ij, t6, t8, d6, d8, edisp, gdisp real(wp) :: dE, dG(3), dS(3, 3) cutoff2 = cutoff*cutoff !$omp parallel do schedule(runtime) default(none) & !$omp reduction(+:energy, gradient, sigma, dEdcn, dEdq) & !$omp shared(mol, self, c6, dc6dcn, dc6dq, trans, cutoff2, r4r2) & !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r0ij, rrij, c6ij, t6, t8, & !$omp& d6, d8, edisp, gdisp, dE, dG, dS) do iat = 1, mol%nat izp = mol%id(iat) do jat = 1, iat jzp = mol%id(jat) rrij = 3*r4r2(izp)*r4r2(jzp) r0ij = self%a1 * sqrt(rrij) + self%a2 c6ij = c6(jat, iat) do jtr = 1, size(trans, 2) vec(:) = mol%xyz(:, iat) - (mol%xyz(:, jat) + trans(:, jtr)) r2 = vec(1)*vec(1) + vec(2)*vec(2) + vec(3)*vec(3) if (r2 > cutoff2 .or. r2 < epsilon(1.0_wp)) cycle t6 = 1.0_wp/(r2**3 + r0ij**6) t8 = 1.0_wp/(r2**4 + r0ij**8) d6 = -6*r2**2*t6**2 d8 = -8*r2**3*t8**2 edisp = self%s6*t6 + self%s8*rrij*t8 gdisp = self%s6*d6 + self%s8*rrij*d8 dE = -c6ij*edisp * 0.5_wp dG(:) = -c6ij*gdisp*vec dS(:, :) = spread(dG, 1, 3) * spread(vec, 2, 3) * 0.5_wp energy(iat) = energy(iat) + dE dEdcn(iat) = dEdcn(iat) - dc6dcn(iat, jat) * edisp dEdq(iat) = dEdq(iat) - dc6dq(iat, jat) * edisp sigma(:, :) = sigma + dS if (iat /= jat) then energy(jat) = energy(jat) + dE dEdcn(jat) = dEdcn(jat) - dc6dcn(jat, iat) * edisp dEdq(jat) = dEdq(jat) - dc6dq(jat, iat) * edisp gradient(:, iat) = gradient(:, iat) + dG gradient(:, jat) = gradient(:, jat) - dG sigma(:, :) = sigma + dS end if end do end do end do end subroutine get_dispersion_derivs