Wrapper to handle the evaluation of dispersion energy and derivatives
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(structure_type), | intent(in) | :: | mol |
Molecular structure data |
||
class(dispersion_model), | intent(in) | :: | disp |
Dispersion model |
||
class(damping_param), | intent(in) | :: | param |
Damping parameters |
||
type(realspace_cutoff), | intent(in) | :: | cutoff |
Realspace cutoffs |
||
real(kind=wp), | intent(out) | :: | energy |
Dispersion energy |
||
real(kind=wp), | intent(out), | optional, | contiguous | :: | gradient(:,:) |
Dispersion gradient |
real(kind=wp), | intent(out), | optional, | contiguous | :: | sigma(:,:) |
Dispersion virial |
subroutine get_dispersion(mol, disp, param, cutoff, energy, gradient, sigma) !DEC$ ATTRIBUTES DLLEXPORT :: get_dispersion !> Molecular structure data class(structure_type), intent(in) :: mol !> Dispersion model class(dispersion_model), intent(in) :: disp !> Damping parameters class(damping_param), intent(in) :: param !> Realspace cutoffs type(realspace_cutoff), intent(in) :: cutoff !> Dispersion energy real(wp), intent(out) :: energy !> Dispersion gradient real(wp), intent(out), contiguous, optional :: gradient(:, :) !> Dispersion virial real(wp), intent(out), contiguous, optional :: sigma(:, :) logical :: grad integer :: mref real(wp), allocatable :: cn(:) real(wp), allocatable :: q(:), dqdr(:, :, :), dqdL(:, :, :) real(wp), allocatable :: gwvec(:, :, :), gwdcn(:, :, :), gwdq(:, :, :) real(wp), allocatable :: c6(:, :), dc6dcn(:, :), dc6dq(:, :) real(wp), allocatable :: dEdcn(:), dEdq(:), energies(:) real(wp), allocatable :: lattr(:, :) mref = maxval(disp%ref) grad = present(gradient).or.present(sigma) allocate(cn(mol%nat)) call get_lattice_points(mol%periodic, mol%lattice, cutoff%cn, lattr) call get_coordination_number(mol, lattr, cutoff%cn, disp%rcov, disp%en, cn) allocate(q(mol%nat)) if (grad) allocate(dqdr(3, mol%nat, mol%nat), dqdL(3, 3, mol%nat)) call get_charges(mol, q, dqdr, dqdL) allocate(gwvec(mref, mol%nat, disp%ncoup)) if (grad) allocate(gwdcn(mref, mol%nat, disp%ncoup), gwdq(mref, mol%nat, disp%ncoup)) call disp%weight_references(mol, cn, q, gwvec, gwdcn, gwdq) allocate(c6(mol%nat, mol%nat)) if (grad) allocate(dc6dcn(mol%nat, mol%nat), dc6dq(mol%nat, mol%nat)) call disp%get_atomic_c6(mol, gwvec, gwdcn, gwdq, c6, dc6dcn, dc6dq) allocate(energies(mol%nat)) energies(:) = 0.0_wp if (grad) then allocate(dEdcn(mol%nat), dEdq(mol%nat)) dEdcn(:) = 0.0_wp dEdq(:) = 0.0_wp gradient(:, :) = 0.0_wp sigma(:, :) = 0.0_wp end if call get_lattice_points(mol%periodic, mol%lattice, cutoff%disp2, lattr) call param%get_dispersion2(mol, lattr, cutoff%disp2, disp%r4r2, & & c6, dc6dcn, dc6dq, energies, dEdcn, dEdq, gradient, sigma) if (grad) then call d4_gemv(dqdr, dEdq, gradient, beta=1.0_wp) call d4_gemv(dqdL, dEdq, sigma, beta=1.0_wp) end if q(:) = 0.0_wp call disp%weight_references(mol, cn, q, gwvec, gwdcn, gwdq) call disp%get_atomic_c6(mol, gwvec, gwdcn, gwdq, c6, dc6dcn, dc6dq) call get_lattice_points(mol%periodic, mol%lattice, cutoff%disp3, lattr) call param%get_dispersion3(mol, lattr, cutoff%disp3, disp%r4r2, & & c6, dc6dcn, dc6dq, energies, dEdcn, dEdq, gradient, sigma) if (grad) then call add_coordination_number_derivs(mol, lattr, cutoff%cn, & & disp%rcov, disp%en, dEdcn, gradient, sigma) end if energy = sum(energies) end subroutine get_dispersion