! This file is part of dftd4. ! SPDX-Identifier: LGPL-3.0-or-later ! ! dftd4 is free software: you can redistribute it and/or modify it under ! the terms of the Lesser GNU General Public License as published by ! the Free Software Foundation, either version 3 of the License, or ! (at your option) any later version. ! ! dftd4 is distributed in the hope that it will be useful, ! but WITHOUT ANY WARRANTY; without even the implied warranty of ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! Lesser GNU General Public License for more details. ! ! You should have received a copy of the Lesser GNU General Public License ! along with dftd4. If not, see <https://www.gnu.org/licenses/>. !> Numerical differentation of DFT-D4 model module dftd4_numdiff use dftd4_cutoff, only : realspace_cutoff use dftd4_damping, only : damping_param use dftd4_disp, only : get_dispersion use dftd4_model, only : dispersion_model use mctc_env, only : wp use mctc_io, only : structure_type implicit none private public :: get_dispersion_hessian contains !> Evaluate hessian matrix by numerical differention subroutine get_dispersion_hessian(mol, disp, param, cutoff, hessian) !DEC$ ATTRIBUTES DLLEXPORT :: get_dispersion_hessian !> 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 hessian real(wp), intent(out) :: hessian(:, :, :, :) integer :: iat, ix real(wp), parameter :: step = 1.0e-4_wp type(structure_type) :: displ real(wp) :: el, er real(wp), allocatable :: gl(:, :), gr(:, :), sl(:, :), sr(:, :) hessian(:, :, :, :) = 0.0_wp !$omp parallel default(none) & !$omp private(iat, ix, displ, er, el, gr, gl, sr, sl) & !$omp shared(mol, disp, param, cutoff, hessian) displ = mol allocate(gl(3, mol%nat), gr(3, mol%nat), sl(3, 3), sr(3, 3)) !$omp do schedule(dynamic) collapse(2) do iat = 1, mol%nat do ix = 1, 3 displ%xyz(ix, iat) = mol%xyz(ix, iat) + step call get_dispersion(displ, disp, param, cutoff, el, gl, sl) displ%xyz(ix, iat) = mol%xyz(ix, iat) - step call get_dispersion(displ, disp, param, cutoff, er, gr, sr) displ%xyz(ix, iat) = mol%xyz(ix, iat) hessian(:, :, ix, iat) = (gl - gr) / (2 * step) end do end do !$omp end parallel end subroutine get_dispersion_hessian end module dftd4_numdiff