LCOV - code coverage report
Current view: top level - src - qs_dispersion_d3.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:561f475) Lines: 99.2 % 645 640
Test Date: 2026-06-21 06:48:54 Functions: 100.0 % 6 6

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Calculation of D3 dispersion
      10              : !> \author JGH
      11              : ! **************************************************************************************************
      12              : MODULE qs_dispersion_d3
      13              : 
      14              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      15              :                                               get_atomic_kind,&
      16              :                                               get_atomic_kind_set
      17              :    USE atprop_types,                    ONLY: atprop_array_init,&
      18              :                                               atprop_type
      19              :    USE cell_types,                      ONLY: cell_type,&
      20              :                                               get_cell,&
      21              :                                               pbc,&
      22              :                                               plane_distance
      23              :    USE cp_files,                        ONLY: close_file,&
      24              :                                               open_file
      25              :    USE input_constants,                 ONLY: vdw_pairpot_dftd3,&
      26              :                                               vdw_pairpot_dftd3bj
      27              :    USE kinds,                           ONLY: dp
      28              :    USE mathconstants,                   ONLY: twopi
      29              :    USE message_passing,                 ONLY: mp_para_env_type
      30              :    USE molecule_types,                  ONLY: molecule_type
      31              :    USE particle_types,                  ONLY: particle_type
      32              :    USE physcon,                         ONLY: kcalmol
      33              :    USE qs_dispersion_cnum,              ONLY: d3_cnumber,&
      34              :                                               dcnum_distribute,&
      35              :                                               dcnum_type,&
      36              :                                               exclude_d3_kind_pair
      37              :    USE qs_dispersion_types,             ONLY: dftd3_pp,&
      38              :                                               qs_atom_dispersion_type,&
      39              :                                               qs_dispersion_type
      40              :    USE qs_dispersion_utils,             ONLY: cellhash
      41              :    USE qs_environment_types,            ONLY: get_qs_env,&
      42              :                                               qs_environment_type
      43              :    USE qs_force_types,                  ONLY: qs_force_type
      44              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      45              :                                               qs_kind_type
      46              :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
      47              :                                               neighbor_list_iterate,&
      48              :                                               neighbor_list_iterator_create,&
      49              :                                               neighbor_list_iterator_p_type,&
      50              :                                               neighbor_list_iterator_release,&
      51              :                                               neighbor_list_set_p_type
      52              :    USE virial_methods,                  ONLY: virial_pair_force
      53              :    USE virial_types,                    ONLY: virial_type
      54              : #include "./base/base_uses.f90"
      55              : 
      56              :    IMPLICIT NONE
      57              : 
      58              :    PRIVATE
      59              : 
      60              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_dispersion_d3'
      61              : 
      62              :    PUBLIC :: calculate_dispersion_d3_pairpot, dftd3_c6_param
      63              : 
      64              : ! **************************************************************************************************
      65              : 
      66              : CONTAINS
      67              : 
      68              : ! **************************************************************************************************
      69              : !> \brief ...
      70              : !> \param qs_env ...
      71              : !> \param dispersion_env ...
      72              : !> \param evdw ...
      73              : !> \param calculate_forces ...
      74              : !> \param unit_nr ...
      75              : !> \param atevdw ...
      76              : ! **************************************************************************************************
      77         5560 :    SUBROUTINE calculate_dispersion_d3_pairpot(qs_env, dispersion_env, evdw, calculate_forces, &
      78         5560 :                                               unit_nr, atevdw)
      79              : 
      80              :       TYPE(qs_environment_type), POINTER                 :: qs_env
      81              :       TYPE(qs_dispersion_type), POINTER                  :: dispersion_env
      82              :       REAL(KIND=dp), INTENT(OUT)                         :: evdw
      83              :       LOGICAL, INTENT(IN)                                :: calculate_forces
      84              :       INTEGER, INTENT(IN)                                :: unit_nr
      85              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL              :: atevdw
      86              : 
      87              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_dispersion_d3_pairpot'
      88              : 
      89              :       INTEGER :: atom_a, atom_b, atom_c, atom_d, handle, hashb, hashc, i, ia, iat, iatom, icx, &
      90              :          icy, icz, idmp, ikind, ilist, imol, jatom, jkind, katom, kkind, kstart, latom, lkind, &
      91              :          max_elem, maxc, mepos, na, natom, nb, nc, nkind, num_pe, za, zb, zc
      92         5560 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind, atomnumber, kind_of
      93              :       INTEGER, DIMENSION(3)                              :: cell_b, cell_c, ncell, periodic
      94         5560 :       INTEGER, DIMENSION(:), POINTER                     :: atom_list
      95              :       LOGICAL :: atenergy, atex, debugall, domol, exclude_pair, floating_a, floating_b, &
      96              :          floating_c, ghost_a, ghost_b, ghost_c, is000, use_virial
      97         5560 :       LOGICAL, ALLOCATABLE, DIMENSION(:)                 :: dodisp, exclude
      98              :       REAL(KIND=dp) :: a1, a2, alp6, alp8, ang, c6, c8, c9, cc6ab, cc6bc, cc6ca, cnum, dc6a, dc6b, &
      99              :          dc8a, dc8b, dcc6aba, dcc6abb, dcc6bcb, dcc6bcc, dcc6caa, dcc6cac, de6, de8, de91, de921, &
     100              :          de922, dea, dfdab6, dfdab8, dfdabc, dr, drk, e6, e6tot, e8, e8tot, e9, e9tot, elrc6, &
     101              :          elrc8, elrc9, eps_cn, esrb, f0ab, fac, fac0, fdab6, fdab8, fdabc, gsrb, kgc8, nab, nabc, &
     102              :          r0, r0ab, r2ab, r2abc, r2bc, r2ca, r6, r8, rabc, rc2, rcc, rcut, rs6, rs8, s1, s2, s3, &
     103              :          s6, s8, s8i, s9, srbe, ssrb, t1srb, t2srb
     104         5560 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: atom2mol, c6d2, cnkind, cnumbers, &
     105         5560 :                                                             cnumfix, radd2
     106         5560 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: rcpbc
     107              :       REAL(KIND=dp), DIMENSION(3)                        :: fdij, fdik, ra, rab, rb, rb0, rbc, rc, &
     108              :                                                             rc0, rca, rij, rik, sab_max
     109              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: pv_virial_thread
     110         5560 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: atener
     111         5560 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     112              :       TYPE(atprop_type), POINTER                         :: atprop
     113              :       TYPE(cell_type), POINTER                           :: cell
     114         5560 :       TYPE(dcnum_type), ALLOCATABLE, DIMENSION(:)        :: dcnum
     115         5560 :       TYPE(molecule_type), DIMENSION(:), POINTER         :: molecule_set
     116              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     117              :       TYPE(neighbor_list_iterator_p_type), &
     118         5560 :          DIMENSION(:), POINTER                           :: nl_iterator
     119              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     120         5560 :          POINTER                                         :: sab_vdw
     121         5560 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     122              :       TYPE(qs_atom_dispersion_type), POINTER             :: disp_a, disp_b, disp_c
     123         5560 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
     124         5560 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     125              :       TYPE(virial_type), POINTER                         :: virial
     126              : 
     127         5560 :       CALL timeset(routineN, handle)
     128              : 
     129         5560 :       evdw = 0._dp
     130              : 
     131         5560 :       NULLIFY (atomic_kind_set, qs_kind_set, sab_vdw)
     132              : 
     133              :       CALL get_qs_env(qs_env=qs_env, nkind=nkind, natom=natom, atomic_kind_set=atomic_kind_set, &
     134         5560 :                       qs_kind_set=qs_kind_set, cell=cell, virial=virial, para_env=para_env, atprop=atprop)
     135              : 
     136         5560 :       debugall = dispersion_env%verbose
     137              : 
     138              :       ! atomic energy and stress arrays
     139         5560 :       atenergy = atprop%energy
     140         5560 :       IF (atenergy) THEN
     141           88 :          CALL atprop_array_init(atprop%atevdw, natom)
     142           88 :          atener => atprop%atevdw
     143              :       END IF
     144              :       ! external atomic energy
     145         5560 :       atex = .FALSE.
     146         5560 :       IF (PRESENT(atevdw)) THEN
     147            2 :          atex = .TRUE.
     148              :       END IF
     149              : 
     150         5560 :       NULLIFY (particle_set)
     151         5560 :       CALL get_qs_env(qs_env=qs_env, particle_set=particle_set)
     152         5560 :       natom = SIZE(particle_set)
     153              : 
     154         5560 :       NULLIFY (force)
     155         5560 :       CALL get_qs_env(qs_env=qs_env, force=force)
     156         5560 :       CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind, kind_of=kind_of)
     157         5560 :       use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
     158         5560 :       pv_virial_thread(:, :) = 0._dp
     159              : 
     160        44480 :       ALLOCATE (dodisp(nkind), exclude(nkind), atomnumber(nkind), c6d2(nkind), radd2(nkind))
     161        18626 :       DO ikind = 1, nkind
     162        13066 :          CALL get_atomic_kind(atomic_kind_set(ikind), z=za)
     163        13066 :          CALL get_qs_kind(qs_kind_set(ikind), dispersion=disp_a, ghost=ghost_a, floating=floating_a)
     164        13066 :          dodisp(ikind) = disp_a%defined
     165        13066 :          exclude(ikind) = ghost_a .OR. floating_a
     166        13066 :          atomnumber(ikind) = za
     167        13066 :          c6d2(ikind) = disp_a%c6
     168        31692 :          radd2(ikind) = disp_a%vdw_radii
     169              :       END DO
     170              : 
     171        16680 :       ALLOCATE (rcpbc(3, natom))
     172        54090 :       DO iatom = 1, natom
     173        54090 :          rcpbc(:, iatom) = pbc(particle_set(iatom)%r(:), cell)
     174              :       END DO
     175              : 
     176         5560 :       rcut = 2._dp*dispersion_env%rc_disp
     177         5560 :       rc2 = rcut*rcut
     178              : 
     179         5560 :       maxc = SIZE(dispersion_env%c6ab, 3)
     180         5560 :       max_elem = SIZE(dispersion_env%c6ab, 1)
     181         5560 :       alp6 = dispersion_env%alp
     182         5560 :       alp8 = alp6 + 2._dp
     183         5560 :       s6 = dispersion_env%s6
     184         5560 :       s8 = dispersion_env%s8
     185         5560 :       s9 = dispersion_env%s6
     186         5560 :       rs6 = dispersion_env%sr6
     187         5560 :       rs8 = 1._dp
     188         5560 :       a1 = dispersion_env%a1
     189         5560 :       a2 = dispersion_env%a2
     190         5560 :       eps_cn = dispersion_env%eps_cn
     191         5560 :       e6tot = 0._dp
     192         5560 :       e8tot = 0._dp
     193         5560 :       e9tot = 0._dp
     194         5560 :       esrb = 0._dp
     195         5560 :       domol = dispersion_env%domol
     196              :       ! molecule correction
     197         5560 :       kgc8 = dispersion_env%kgc8
     198         5560 :       IF (domol) THEN
     199            2 :          CALL get_qs_env(qs_env=qs_env, molecule_set=molecule_set)
     200            6 :          ALLOCATE (atom2mol(natom))
     201            6 :          DO imol = 1, SIZE(molecule_set)
     202           16 :             DO iat = molecule_set(imol)%first_atom, molecule_set(imol)%last_atom
     203           14 :                atom2mol(iat) = imol
     204              :             END DO
     205              :          END DO
     206              :       END IF
     207              :       ! damping type
     208         5560 :       idmp = 0
     209         5560 :       IF (dispersion_env%pp_type == vdw_pairpot_dftd3) THEN
     210              :          idmp = 1
     211         5288 :       ELSE IF (dispersion_env%pp_type == vdw_pairpot_dftd3bj) THEN
     212         5288 :          idmp = 2
     213              :       END IF
     214              :       ! SRB parameters
     215         5560 :       ssrb = dispersion_env%srb_params(1)
     216         5560 :       gsrb = dispersion_env%srb_params(2)
     217         5560 :       t1srb = dispersion_env%srb_params(3)
     218         5560 :       t2srb = dispersion_env%srb_params(4)
     219              : 
     220         5560 :       IF (unit_nr > 0) THEN
     221           45 :          WRITE (unit_nr, *) " Scaling parameter (s6) ", s6
     222           45 :          WRITE (unit_nr, *) " Scaling parameter (s8) ", s8
     223           45 :          IF (dispersion_env%pp_type == vdw_pairpot_dftd3) THEN
     224           20 :             WRITE (unit_nr, *) " Zero Damping parameter (sr6)", rs6
     225           20 :             WRITE (unit_nr, *) " Zero Damping parameter (sr8)", rs8
     226           25 :          ELSE IF (dispersion_env%pp_type == vdw_pairpot_dftd3bj) THEN
     227           25 :             WRITE (unit_nr, *) " BJ Damping parameter (a1) ", a1
     228           25 :             WRITE (unit_nr, *) " BJ Damping parameter (a2) ", a2
     229              :          END IF
     230           45 :          WRITE (unit_nr, *) " Cutoff coordination numbers", eps_cn
     231           45 :          IF (dispersion_env%lrc) THEN
     232            1 :             WRITE (unit_nr, *) " Apply a long range correction"
     233              :          END IF
     234           45 :          IF (dispersion_env%srb) THEN
     235            3 :             WRITE (unit_nr, *) " Apply a short range bond correction"
     236            3 :             WRITE (unit_nr, *) " SRB parameters (s,g,t1,t2) ", ssrb, gsrb, t1srb, t2srb
     237              :          END IF
     238           45 :          IF (domol) THEN
     239            1 :             WRITE (unit_nr, *) " Inter-molecule scaling parameter (s8) ", kgc8
     240              :          END IF
     241              :       END IF
     242              :       ! Calculate coordination numbers
     243         5560 :       NULLIFY (particle_set)
     244         5560 :       CALL get_qs_env(qs_env=qs_env, particle_set=particle_set)
     245         5560 :       natom = SIZE(particle_set)
     246        16680 :       ALLOCATE (cnumbers(natom))
     247         5560 :       cnumbers = 0._dp
     248              : 
     249         5560 :       IF (calculate_forces .OR. debugall) THEN
     250        12318 :          ALLOCATE (dcnum(natom))
     251        10690 :          dcnum(:)%neighbors = 0
     252        10690 :          DO iatom = 1, natom
     253        10690 :             ALLOCATE (dcnum(iatom)%nlist(10), dcnum(iatom)%dvals(10), dcnum(iatom)%rik(3, 10))
     254              :          END DO
     255              :       ELSE
     256         9492 :          ALLOCATE (dcnum(1))
     257              :       END IF
     258              : 
     259              :       CALL d3_cnumber(qs_env, dispersion_env, cnumbers, dcnum, exclude, atomnumber, &
     260         5560 :                       calculate_forces, 1)
     261              : 
     262         5560 :       CALL para_env%sum(cnumbers)
     263              : 
     264              :       ! for parallel runs we have to update dcnum on all processors
     265         5560 :       IF (calculate_forces .OR. debugall) THEN
     266          814 :          CALL dcnum_distribute(dcnum, para_env)
     267          814 :          IF (unit_nr > 0 .AND. SIZE(dcnum) > 0) THEN
     268            4 :             WRITE (unit_nr, *)
     269            4 :             WRITE (unit_nr, *) "  ATOM       Coordination   Neighbors"
     270           19 :             DO i = 1, natom
     271           19 :                WRITE (unit_nr, "(I6,F20.10,I12)") i, cnumbers(i), dcnum(i)%neighbors
     272              :             END DO
     273            4 :             WRITE (unit_nr, *)
     274              :          END IF
     275              :       END IF
     276              : 
     277         5560 :       nab = 0._dp
     278         5560 :       nabc = 0._dp
     279         5560 :       IF (dispersion_env%doabc) THEN
     280          112 :          rcc = 2._dp*dispersion_env%rc_disp
     281          112 :          CALL get_cell(cell=cell, periodic=periodic)
     282          112 :          sab_max(1) = rcc/plane_distance(1, 0, 0, cell)
     283          112 :          sab_max(2) = rcc/plane_distance(0, 1, 0, cell)
     284          112 :          sab_max(3) = rcc/plane_distance(0, 0, 1, cell)
     285          448 :          ncell(:) = (INT(sab_max(:)) + 1)*periodic(:)
     286          112 :          IF (unit_nr > 0) THEN
     287            4 :             WRITE (unit_nr, *) " Calculate C9 Terms"
     288            4 :             WRITE (unit_nr, "(A,T20,I3,A,I3)") "  Search in cells ", -ncell(1), ":", ncell(1)
     289            4 :             WRITE (unit_nr, "(T20,I3,A,I3)") - ncell(2), ":", ncell(2)
     290            4 :             WRITE (unit_nr, "(T20,I3,A,I3)") - ncell(3), ":", ncell(3)
     291            4 :             WRITE (unit_nr, *)
     292              :          END IF
     293          112 :          IF (dispersion_env%c9cnst) THEN
     294           66 :             IF (unit_nr > 0) WRITE (unit_nr, *) " Use reference coordination numbers for C9 term"
     295          198 :             ALLOCATE (cnumfix(natom))
     296           66 :             cnumfix = 0._dp
     297              :             ! first use the default values
     298          326 :             DO iatom = 1, natom
     299          260 :                ikind = kind_of(iatom)
     300          260 :                CALL get_atomic_kind(atomic_kind_set(ikind), z=za)
     301          326 :                cnumfix(iatom) = dispersion_env%cn(za)
     302              :             END DO
     303              :             ! now check for changes from default
     304           66 :             IF (ASSOCIATED(dispersion_env%cnkind)) THEN
     305           12 :                DO i = 1, SIZE(dispersion_env%cnkind)
     306            6 :                   ikind = dispersion_env%cnkind(i)%kind
     307            6 :                   cnum = dispersion_env%cnkind(i)%cnum
     308            6 :                   CPASSERT(ikind <= nkind)
     309            6 :                   CPASSERT(ikind > 0)
     310            6 :                   CALL get_atomic_kind(atomic_kind_set(ikind), natom=na, atom_list=atom_list)
     311           32 :                   DO ia = 1, na
     312           20 :                      iatom = atom_list(ia)
     313           26 :                      cnumfix(iatom) = cnum
     314              :                   END DO
     315              :                END DO
     316              :             END IF
     317           66 :             IF (ASSOCIATED(dispersion_env%cnlist)) THEN
     318            6 :                DO i = 1, SIZE(dispersion_env%cnlist)
     319           14 :                   DO ilist = 1, dispersion_env%cnlist(i)%natom
     320            8 :                      iatom = dispersion_env%cnlist(i)%atom(ilist)
     321           12 :                      cnumfix(iatom) = dispersion_env%cnlist(i)%cnum
     322              :                   END DO
     323              :                END DO
     324              :             END IF
     325           66 :             IF (unit_nr > 0) THEN
     326            5 :                DO i = 1, natom
     327            5 :                   IF (ABS(cnumbers(i) - cnumfix(i)) > 0.5_dp) THEN
     328            0 :                      WRITE (unit_nr, "(A,T20,A,I6,T41,2F10.3)") "  Difference in CN ", "Atom:", &
     329            0 :                         i, cnumbers(i), cnumfix(i)
     330              :                   END IF
     331              :                END DO
     332            1 :                WRITE (unit_nr, *)
     333              :             END IF
     334              :          END IF
     335              :       END IF
     336              : 
     337         5560 :       sab_vdw => dispersion_env%sab_vdw
     338              : 
     339         5560 :       num_pe = 1
     340         5560 :       CALL neighbor_list_iterator_create(nl_iterator, sab_vdw, nthread=num_pe)
     341              : 
     342         5560 :       mepos = 0
     343      8888015 :       DO WHILE (neighbor_list_iterate(nl_iterator, mepos=mepos) == 0)
     344      8882455 :          CALL get_iterator_info(nl_iterator, mepos=mepos, ikind=ikind, jkind=jkind, iatom=iatom, jatom=jatom, r=rij)
     345              : 
     346      8882455 :          IF (exclude(ikind) .OR. exclude(jkind)) CYCLE
     347              : 
     348      8882398 :          IF (.NOT. (dodisp(ikind) .AND. dodisp(jkind))) CYCLE
     349              : 
     350      8882164 :          za = atomnumber(ikind)
     351      8882164 :          zb = atomnumber(jkind)
     352              :          ! vdW potential
     353     35528656 :          dr = SQRT(SUM(rij(:)**2))
     354      8887724 :          IF (dr <= rcut) THEN
     355      8882164 :             nab = nab + 1._dp
     356      8882164 :             fac = 1._dp
     357      8882164 :             IF (iatom == jatom) fac = 0.5_dp
     358      8882164 :             IF (disp_a%type == dftd3_pp .AND. dr > 0.001_dp) THEN
     359      8857596 :                IF (dispersion_env%nd3_exclude_pair > 0) THEN
     360              :                   CALL exclude_d3_kind_pair(dispersion_env%d3_exclude_pair, ikind, jkind, &
     361          320 :                                             exclude=exclude_pair)
     362          320 :                   IF (exclude_pair) CYCLE
     363              :                END IF
     364              :                ! C6 coefficient
     365              :                CALL getc6(maxc, max_elem, dispersion_env%c6ab, dispersion_env%maxci, za, zb, &
     366      8857364 :                           cnumbers(iatom), cnumbers(jatom), dispersion_env%k3, c6, dc6a, dc6b)
     367      8857364 :                c8 = 3.0d0*c6*dispersion_env%r2r4(za)*dispersion_env%r2r4(zb)
     368      8857364 :                dc8a = 3.0d0*dc6a*dispersion_env%r2r4(za)*dispersion_env%r2r4(zb)
     369      8857364 :                dc8b = 3.0d0*dc6b*dispersion_env%r2r4(za)*dispersion_env%r2r4(zb)
     370      8857364 :                r6 = dr**6
     371      8857364 :                r8 = r6*dr*dr
     372      8857364 :                s8i = s8
     373      8857364 :                IF (domol) THEN
     374         3568 :                   IF (atom2mol(iatom) /= atom2mol(jatom)) THEN
     375         1452 :                      s8i = kgc8
     376              :                   END IF
     377              :                END IF
     378              :                ! damping
     379      8857364 :                IF (idmp == 1) THEN
     380              :                   ! zero
     381      3890544 :                   CALL damping_d3(dr, dispersion_env%r0ab(za, zb), rs6, alp6, rcut, fdab6, dfdab6)
     382      3890544 :                   CALL damping_d3(dr, dispersion_env%r0ab(za, zb), rs8, alp8, rcut, fdab8, dfdab8)
     383      3890544 :                   e6 = s6*fac*c6*fdab6/r6
     384      3890544 :                   e8 = s8i*fac*c8*fdab8/r8
     385      4966820 :                ELSE IF (idmp == 2) THEN
     386              :                   ! BJ
     387      4966820 :                   r0ab = SQRT(3.0d0*dispersion_env%r2r4(za)*dispersion_env%r2r4(zb))
     388      4966820 :                   f0ab = a1*r0ab + a2
     389      4966820 :                   fdab6 = 1.0_dp/(r6 + f0ab**6)
     390      4966820 :                   fdab8 = 1.0_dp/(r8 + f0ab**8)
     391      4966820 :                   e6 = s6*fac*c6*fdab6
     392      4966820 :                   e8 = s8i*fac*c8*fdab8
     393              :                ELSE
     394            0 :                   CPABORT("Unknown DFT-D3 damping function:")
     395              :                END IF
     396      8857364 :                IF (dispersion_env%srb .AND. dr < 30.0d0) THEN
     397          135 :                   srbe = ssrb*(REAL((za*zb), KIND=dp))**t1srb*EXP(-gsrb*dr*dispersion_env%r0ab(za, zb)**t2srb)
     398          135 :                   esrb = esrb + srbe
     399          135 :                   evdw = evdw - srbe
     400              :                ELSE
     401              :                   srbe = 0.0_dp
     402              :                END IF
     403      8857364 :                evdw = evdw - e6 - e8
     404      8857364 :                e6tot = e6tot - e6
     405      8857364 :                e8tot = e8tot - e8
     406      8857364 :                IF (atenergy) THEN
     407      2765506 :                   atener(iatom) = atener(iatom) - 0.5_dp*(e6 + e8 + srbe)
     408      2765506 :                   atener(jatom) = atener(jatom) - 0.5_dp*(e6 + e8 + srbe)
     409              :                END IF
     410      8857364 :                IF (atex) THEN
     411          850 :                   atevdw(iatom) = atevdw(iatom) - 0.5_dp*(e6 + e8 + srbe)
     412          850 :                   atevdw(jatom) = atevdw(jatom) - 0.5_dp*(e6 + e8 + srbe)
     413              :                END IF
     414      8857364 :                IF (calculate_forces) THEN
     415              :                   ! damping
     416      3198770 :                   IF (idmp == 1) THEN
     417              :                      ! zero
     418      1999225 :                      de6 = -s6*c6/r6*(dfdab6 - 6._dp*fdab6/dr)
     419      1999225 :                      de8 = -s8i*c8/r8*(dfdab8 - 8._dp*fdab8/dr)
     420      1199545 :                   ELSE IF (idmp == 2) THEN
     421              :                      ! BJ
     422      1199545 :                      de6 = s6*c6*fdab6*fdab6*6.0_dp*dr**5
     423      1199545 :                      de8 = s8i*c8*fdab8*fdab8*8.0_dp*dr**7
     424              :                   ELSE
     425            0 :                      CPABORT("Unknown DFT-D3 damping function:")
     426              :                   END IF
     427     12795080 :                   fdij(:) = (de6 + de8)*rij(:)/dr*fac
     428      3198770 :                   IF (dispersion_env%srb .AND. dr < 30.0d0) THEN
     429          172 :                      fdij(:) = fdij(:) + srbe*gsrb*dispersion_env%r0ab(za, zb)**t2srb*rij(:)/dr
     430              :                   END IF
     431      3198770 :                   atom_a = atom_of_kind(iatom)
     432      3198770 :                   atom_b = atom_of_kind(jatom)
     433     12795080 :                   force(ikind)%dispersion(:, atom_a) = force(ikind)%dispersion(:, atom_a) - fdij(:)
     434     12795080 :                   force(jkind)%dispersion(:, atom_b) = force(jkind)%dispersion(:, atom_b) + fdij(:)
     435      3198770 :                   IF (use_virial) THEN
     436      2035489 :                      CALL virial_pair_force(pv_virial_thread, -1._dp, fdij, rij)
     437              :                   END IF
     438              :                   ! forces from the r-dependence of the coordination numbers
     439      3198770 :                   IF (idmp == 1) THEN
     440              :                      ! zero
     441      1999225 :                      dc6a = -s6*fac*dc6a*fdab6/r6
     442      1999225 :                      dc6b = -s6*fac*dc6b*fdab6/r6
     443      1999225 :                      dc8a = -s8i*fac*dc8a*fdab8/r8
     444      1999225 :                      dc8b = -s8i*fac*dc8b*fdab8/r8
     445      1199545 :                   ELSE IF (idmp == 2) THEN
     446              :                      ! BJ
     447      1199545 :                      dc6a = -s6*fac*dc6a*fdab6
     448      1199545 :                      dc6b = -s6*fac*dc6b*fdab6
     449      1199545 :                      dc8a = -s8i*fac*dc8a*fdab8
     450      1199545 :                      dc8b = -s8i*fac*dc8b*fdab8
     451              :                   ELSE
     452            0 :                      CPABORT("Unknown DFT-D3 damping function:")
     453              :                   END IF
     454     43322651 :                   DO i = 1, dcnum(iatom)%neighbors
     455     40123881 :                      katom = dcnum(iatom)%nlist(i)
     456     40123881 :                      kkind = kind_of(katom)
     457    160495524 :                      rik = dcnum(iatom)%rik(:, i)
     458    160495524 :                      drk = SQRT(SUM(rik(:)**2))
     459    160495524 :                      fdik(:) = (dc6a + dc8a)*dcnum(iatom)%dvals(i)*rik(:)/drk
     460     40123881 :                      atom_c = atom_of_kind(katom)
     461    160495524 :                      force(ikind)%dispersion(:, atom_a) = force(ikind)%dispersion(:, atom_a) - fdik(:)
     462    160495524 :                      force(kkind)%dispersion(:, atom_c) = force(kkind)%dispersion(:, atom_c) + fdik(:)
     463     43322651 :                      IF (use_virial) THEN
     464     29100575 :                         CALL virial_pair_force(pv_virial_thread, -1._dp, fdik, rik)
     465              :                      END IF
     466              :                   END DO
     467     43321099 :                   DO i = 1, dcnum(jatom)%neighbors
     468     40122329 :                      katom = dcnum(jatom)%nlist(i)
     469     40122329 :                      kkind = kind_of(katom)
     470    160489316 :                      rik = dcnum(jatom)%rik(:, i)
     471    160489316 :                      drk = SQRT(SUM(rik(:)**2))
     472    160489316 :                      fdik(:) = (dc6b + dc8b)*dcnum(jatom)%dvals(i)*rik(:)/drk
     473     40122329 :                      atom_c = atom_of_kind(katom)
     474    160489316 :                      force(jkind)%dispersion(:, atom_b) = force(jkind)%dispersion(:, atom_b) - fdik(:)
     475    160489316 :                      force(kkind)%dispersion(:, atom_c) = force(kkind)%dispersion(:, atom_c) + fdik(:)
     476     43321099 :                      IF (use_virial) THEN
     477     29097827 :                         CALL virial_pair_force(pv_virial_thread, -1._dp, fdik, rik)
     478              :                      END IF
     479              :                   END DO
     480              :                END IF
     481      8857364 :                IF (dispersion_env%doabc) THEN
     482        16192 :                   CALL get_iterator_info(nl_iterator, cell=cell_b)
     483        16192 :                   hashb = cellhash(cell_b, ncell)
     484        25262 :                   is000 = (ALL(cell_b == 0))
     485       259072 :                   rb0(:) = MATMUL(cell%hmat, cell_b)
     486        16192 :                   ra(:) = pbc(particle_set(iatom)%r(:), cell)
     487        80960 :                   rb(:) = pbc(particle_set(jatom)%r(:), cell) + rb0
     488        64768 :                   r2ab = SUM((ra - rb)**2)
     489       105328 :                   DO icx = -ncell(1), ncell(1)
     490       665904 :                      DO icy = -ncell(2), ncell(2)
     491      4632608 :                         DO icz = -ncell(3), ncell(3)
     492      3982896 :                            cell_c(1) = icx
     493      3982896 :                            cell_c(2) = icy
     494      3982896 :                            cell_c(3) = icz
     495      3982896 :                            hashc = cellhash(cell_c, ncell)
     496      4648800 :                            IF (is000 .AND. (ALL(cell_c == 0))) THEN
     497              :                               ! CASE 1: all atoms in (000), use only ordered triples
     498         1206 :                               kstart = MAX(jatom + 1, iatom + 1)
     499         1206 :                               fac0 = 1.0_dp
     500      3981690 :                            ELSE IF (is000) THEN
     501              :                               ! CASE 2: AB in (000), C in other cell
     502              :                               !         This case covers also all instances with BC in same
     503              :                               !         cell not (000)
     504              :                               kstart = 1
     505              :                               fac0 = 1.0_dp
     506              :                            ELSE
     507              :                               ! These are case 2 again, cycle
     508      3948058 :                               IF (hashc == hashb) CYCLE
     509      4582770 :                               IF (ALL(cell_c == 0)) CYCLE
     510              :                               ! CASE 3: A in (000) and B and C in different cells
     511              :                               kstart = 1
     512              :                               fac0 = 1.0_dp/3.0_dp
     513              :                            END IF
     514     63246784 :                            rc0 = MATMUL(cell%hmat, cell_c)
     515     15614318 :                            DO katom = kstart, natom
     516     11100818 :                               kkind = kind_of(katom)
     517     11100818 :                               IF (exclude(kkind) .OR. .NOT. dodisp(kkind)) CYCLE
     518     44316664 :                               rc(:) = rcpbc(:, katom) + rc0(:)
     519     44316664 :                               r2bc = SUM((rb - rc)**2)
     520     11079166 :                               IF (r2bc >= rc2) CYCLE
     521      9440716 :                               r2ca = SUM((rc - ra)**2)
     522      2360179 :                               IF (r2ca >= rc2) CYCLE
     523      1223808 :                               r2abc = r2ab*r2bc*r2ca
     524      1223808 :                               IF (r2abc <= 0.001_dp) CYCLE
     525      1223808 :                               IF (dispersion_env%nd3_exclude_pair > 0) THEN
     526              :                                  CALL exclude_d3_kind_pair(dispersion_env%d3_exclude_pair, ikind, jkind, &
     527         5066 :                                                            kkind, exclude_pair)
     528         5066 :                                  IF (exclude_pair) CYCLE
     529              :                               END IF
     530              :                               ! this is an empirical scaling
     531      5173928 :                               IF (r2abc <= 0.01*rc2*rc2*rc2) THEN
     532        54030 :                                  kkind = kind_of(katom)
     533        54030 :                                  atom_c = atom_of_kind(katom)
     534        54030 :                                  zc = atomnumber(kkind)
     535              :                                  ! avoid double counting!
     536        54030 :                                  fac = 1._dp
     537        54030 :                                  IF (iatom == jatom .OR. iatom == katom .OR. jatom == katom) fac = 0.5_dp
     538        54030 :                                  IF (iatom == jatom .AND. iatom == katom) fac = 1._dp/3._dp
     539        54030 :                                  fac = fac*fac0
     540        54030 :                                  nabc = nabc + 1._dp
     541        54030 :                                  IF (dispersion_env%c9cnst) THEN
     542              :                                     CALL getc6(maxc, max_elem, dispersion_env%c6ab, dispersion_env%maxci, za, zb, &
     543        33752 :                                                cnumfix(iatom), cnumfix(jatom), dispersion_env%k3, cc6ab, dcc6aba, dcc6abb)
     544              :                                     CALL getc6(maxc, max_elem, dispersion_env%c6ab, dispersion_env%maxci, zb, zc, &
     545        33752 :                                                cnumfix(jatom), cnumfix(katom), dispersion_env%k3, cc6bc, dcc6bcb, dcc6bcc)
     546              :                                     CALL getc6(maxc, max_elem, dispersion_env%c6ab, dispersion_env%maxci, zc, za, &
     547        33752 :                                                cnumfix(katom), cnumfix(iatom), dispersion_env%k3, cc6ca, dcc6cac, dcc6caa)
     548              :                                  ELSE
     549              :                                     CALL getc6(maxc, max_elem, dispersion_env%c6ab, dispersion_env%maxci, za, zb, &
     550        20278 :                                                cnumbers(iatom), cnumbers(jatom), dispersion_env%k3, cc6ab, dcc6aba, dcc6abb)
     551              :                                     CALL getc6(maxc, max_elem, dispersion_env%c6ab, dispersion_env%maxci, zb, zc, &
     552        20278 :                                                cnumbers(jatom), cnumbers(katom), dispersion_env%k3, cc6bc, dcc6bcb, dcc6bcc)
     553              :                                     CALL getc6(maxc, max_elem, dispersion_env%c6ab, dispersion_env%maxci, zc, za, &
     554        20278 :                                                cnumbers(katom), cnumbers(iatom), dispersion_env%k3, cc6ca, dcc6cac, dcc6caa)
     555              :                                  END IF
     556        54030 :                                  c9 = -SQRT(cc6ab*cc6bc*cc6ca)
     557        54030 :                                  rabc = r2abc**(1._dp/6._dp)
     558              :                                  r0 = (dispersion_env%r0ab(za, zb)*dispersion_env%r0ab(zb, zc)* &
     559        54030 :                                        dispersion_env%r0ab(zc, za))**(1._dp/3._dp)
     560              :                                  ! bug fixed 3.10.2017
     561              :                                  ! correct value from alp6=14 to 16 as used in original paper
     562        54030 :                                  CALL damping_d3(rabc, r0, 4._dp/3._dp, 16.0_dp, rcut, fdabc, dfdabc)
     563        54030 :                                  s1 = r2ab + r2bc - r2ca
     564        54030 :                                  s2 = r2ab + r2ca - r2bc
     565        54030 :                                  s3 = r2ca + r2bc - r2ab
     566        54030 :                                  ang = 0.375_dp*s1*s2*s3/r2abc + 1.0_dp
     567              : 
     568        54030 :                                  e9 = s9*fac*fdabc*c9*ang/r2abc**1.50d0
     569        54030 :                                  evdw = evdw - e9
     570        54030 :                                  e9tot = e9tot - e9
     571        54030 :                                  IF (atenergy) THEN
     572        20568 :                                     atener(iatom) = atener(iatom) - e9/3._dp
     573        20568 :                                     atener(jatom) = atener(jatom) - e9/3._dp
     574        20568 :                                     atener(katom) = atener(katom) - e9/3._dp
     575              :                                  END IF
     576        54030 :                                  IF (atex) THEN
     577        10284 :                                     atevdw(iatom) = atevdw(iatom) - e9/3._dp
     578        10284 :                                     atevdw(jatom) = atevdw(jatom) - e9/3._dp
     579        10284 :                                     atevdw(katom) = atevdw(katom) - e9/3._dp
     580              :                                  END IF
     581              : 
     582        54030 :                                  IF (calculate_forces) THEN
     583       271500 :                                     rab = rb - ra; rbc = rc - rb; rca = ra - rc
     584        27150 :                                     de91 = s9*fac*dfdabc*c9*ang/r2abc**1.50d0
     585        27150 :                                     de91 = -de91/3._dp*rabc + 3._dp*e9
     586        27150 :                                     dea = s9*fac*fdabc*c9/r2abc**2.50d0*0.75_dp
     587       108600 :                                     fdij(:) = de91*rab(:)/r2ab
     588       108600 :                                     fdij(:) = fdij(:) + dea*s1*s2*s3*rab(:)/r2ab
     589       108600 :                                     fdij(:) = fdij(:) - dea*(s2*s3 + s1*s3 - s1*s2)*rab(:)
     590       108600 :                                     force(ikind)%dispersion(:, atom_a) = force(ikind)%dispersion(:, atom_a) - fdij(:)
     591       108600 :                                     force(jkind)%dispersion(:, atom_b) = force(jkind)%dispersion(:, atom_b) + fdij(:)
     592        27150 :                                     IF (use_virial) THEN
     593        16376 :                                        CALL virial_pair_force(pv_virial_thread, -1._dp, fdij, rab)
     594              :                                     END IF
     595       108600 :                                     fdij(:) = de91*rbc(:)/r2bc
     596       108600 :                                     fdij(:) = fdij(:) + dea*s1*s2*s3*rbc(:)/r2bc
     597       108600 :                                     fdij(:) = fdij(:) - dea*(s2*s3 - s1*s3 + s1*s2)*rbc(:)
     598       108600 :                                     force(jkind)%dispersion(:, atom_b) = force(jkind)%dispersion(:, atom_b) - fdij(:)
     599       108600 :                                     force(kkind)%dispersion(:, atom_c) = force(kkind)%dispersion(:, atom_c) + fdij(:)
     600        27150 :                                     IF (use_virial) THEN
     601        16376 :                                        CALL virial_pair_force(pv_virial_thread, -1._dp, fdij, rbc)
     602              :                                     END IF
     603       108600 :                                     fdij(:) = de91*rca(:)/r2ca
     604       108600 :                                     fdij(:) = fdij(:) + dea*s1*s2*s3*rca(:)/r2ca
     605       108600 :                                     fdij(:) = fdij(:) - dea*(-s2*s3 + s1*s3 + s1*s2)*rca(:)
     606       108600 :                                     force(kkind)%dispersion(:, atom_c) = force(kkind)%dispersion(:, atom_c) - fdij(:)
     607       108600 :                                     force(ikind)%dispersion(:, atom_a) = force(ikind)%dispersion(:, atom_a) + fdij(:)
     608        27150 :                                     IF (use_virial) THEN
     609        16376 :                                        CALL virial_pair_force(pv_virial_thread, -1._dp, fdij, rca)
     610              :                                     END IF
     611              : 
     612        27150 :                                     IF (.NOT. dispersion_env%c9cnst) THEN
     613              :                                        ! forces from the r-dependence of the coordination numbers
     614              :                                        ! atomic stress not implemented
     615              : 
     616        13966 :                                        de91 = 0.5_dp*e9/cc6ab
     617        13966 :                                        de921 = de91*dcc6aba
     618        13966 :                                        de922 = de91*dcc6abb
     619        69354 :                                        DO i = 1, dcnum(iatom)%neighbors
     620        55388 :                                           latom = dcnum(iatom)%nlist(i)
     621        55388 :                                           lkind = kind_of(latom)
     622        55388 :                                           rik(1) = dcnum(iatom)%rik(1, i)
     623        55388 :                                           rik(2) = dcnum(iatom)%rik(2, i)
     624        55388 :                                           rik(3) = dcnum(iatom)%rik(3, i)
     625        55388 :                                           drk = SQRT(rik(1)*rik(1) + rik(2)*rik(2) + rik(3)*rik(3))
     626       221552 :                                           fdik(:) = -de921*dcnum(iatom)%dvals(i)*rik(:)/drk
     627        55388 :                                           atom_d = atom_of_kind(latom)
     628       221552 :                                           force(ikind)%dispersion(:, atom_a) = force(ikind)%dispersion(:, atom_a) - fdik(:)
     629       221552 :                                           force(lkind)%dispersion(:, atom_d) = force(lkind)%dispersion(:, atom_d) + fdik(:)
     630        69354 :                                           IF (use_virial) THEN
     631        55224 :                                              CALL virial_pair_force(pv_virial_thread, -1._dp, fdik, rik)
     632              :                                           END IF
     633              :                                        END DO
     634        69354 :                                        DO i = 1, dcnum(jatom)%neighbors
     635        55388 :                                           latom = dcnum(jatom)%nlist(i)
     636        55388 :                                           lkind = kind_of(latom)
     637        55388 :                                           rik(1) = dcnum(jatom)%rik(1, i)
     638        55388 :                                           rik(2) = dcnum(jatom)%rik(2, i)
     639        55388 :                                           rik(3) = dcnum(jatom)%rik(3, i)
     640        55388 :                                           drk = SQRT(rik(1)*rik(1) + rik(2)*rik(2) + rik(3)*rik(3))
     641       221552 :                                           fdik(:) = -de922*dcnum(jatom)%dvals(i)*rik(:)/drk
     642        55388 :                                           atom_d = atom_of_kind(latom)
     643       221552 :                                           force(jkind)%dispersion(:, atom_b) = force(jkind)%dispersion(:, atom_b) - fdik(:)
     644       221552 :                                           force(lkind)%dispersion(:, atom_d) = force(lkind)%dispersion(:, atom_d) + fdik(:)
     645        69354 :                                           IF (use_virial) THEN
     646        55224 :                                              CALL virial_pair_force(pv_virial_thread, -1._dp, fdik, rik)
     647              :                                           END IF
     648              :                                        END DO
     649              : 
     650        13966 :                                        de91 = 0.5_dp*e9/cc6bc
     651        13966 :                                        de921 = de91*dcc6bcb
     652        13966 :                                        de922 = de91*dcc6bcc
     653        69354 :                                        DO i = 1, dcnum(jatom)%neighbors
     654        55388 :                                           latom = dcnum(jatom)%nlist(i)
     655        55388 :                                           lkind = kind_of(latom)
     656        55388 :                                           rik(1) = dcnum(jatom)%rik(1, i)
     657        55388 :                                           rik(2) = dcnum(jatom)%rik(2, i)
     658        55388 :                                           rik(3) = dcnum(jatom)%rik(3, i)
     659        55388 :                                           drk = SQRT(rik(1)*rik(1) + rik(2)*rik(2) + rik(3)*rik(3))
     660       221552 :                                           fdik(:) = -de921*dcnum(jatom)%dvals(i)*rik(:)/drk
     661        55388 :                                           atom_d = atom_of_kind(latom)
     662       221552 :                                           force(jkind)%dispersion(:, atom_b) = force(jkind)%dispersion(:, atom_b) - fdik(:)
     663       221552 :                                           force(lkind)%dispersion(:, atom_d) = force(lkind)%dispersion(:, atom_d) + fdik(:)
     664        69354 :                                           IF (use_virial) THEN
     665        55224 :                                              CALL virial_pair_force(pv_virial_thread, -1._dp, fdik, rik)
     666              :                                           END IF
     667              :                                        END DO
     668        69354 :                                        DO i = 1, dcnum(katom)%neighbors
     669        55388 :                                           latom = dcnum(katom)%nlist(i)
     670        55388 :                                           lkind = kind_of(latom)
     671        55388 :                                           rik(1) = dcnum(katom)%rik(1, i)
     672        55388 :                                           rik(2) = dcnum(katom)%rik(2, i)
     673        55388 :                                           rik(3) = dcnum(katom)%rik(3, i)
     674        55388 :                                           drk = SQRT(rik(1)*rik(1) + rik(2)*rik(2) + rik(3)*rik(3))
     675       221552 :                                           fdik(:) = -de922*dcnum(katom)%dvals(i)*rik(:)/drk
     676        55388 :                                           atom_d = atom_of_kind(latom)
     677       221552 :                                           force(kkind)%dispersion(:, atom_c) = force(kkind)%dispersion(:, atom_c) - fdik(:)
     678       221552 :                                           force(lkind)%dispersion(:, atom_d) = force(lkind)%dispersion(:, atom_d) + fdik(:)
     679        69354 :                                           IF (use_virial) THEN
     680        55224 :                                              CALL virial_pair_force(pv_virial_thread, -1._dp, fdik, rik)
     681              :                                           END IF
     682              :                                        END DO
     683              : 
     684        13966 :                                        de91 = 0.5_dp*e9/cc6ca
     685        13966 :                                        de921 = de91*dcc6cac
     686        13966 :                                        de922 = de91*dcc6caa
     687        69354 :                                        DO i = 1, dcnum(katom)%neighbors
     688        55388 :                                           latom = dcnum(katom)%nlist(i)
     689        55388 :                                           lkind = kind_of(latom)
     690        55388 :                                           rik(1) = dcnum(katom)%rik(1, i)
     691        55388 :                                           rik(2) = dcnum(katom)%rik(2, i)
     692        55388 :                                           rik(3) = dcnum(katom)%rik(3, i)
     693        55388 :                                           drk = SQRT(rik(1)*rik(1) + rik(2)*rik(2) + rik(3)*rik(3))
     694       221552 :                                           fdik(:) = -de921*dcnum(katom)%dvals(i)*rik(:)/drk
     695        55388 :                                           atom_d = atom_of_kind(latom)
     696       221552 :                                           force(kkind)%dispersion(:, atom_c) = force(kkind)%dispersion(:, atom_c) - fdik(:)
     697       221552 :                                           force(lkind)%dispersion(:, atom_d) = force(lkind)%dispersion(:, atom_d) + fdik(:)
     698        69354 :                                           IF (use_virial) THEN
     699        55224 :                                              CALL virial_pair_force(pv_virial_thread, -1._dp, fdik, rik)
     700              :                                           END IF
     701              :                                        END DO
     702        69354 :                                        DO i = 1, dcnum(iatom)%neighbors
     703        55388 :                                           latom = dcnum(iatom)%nlist(i)
     704        55388 :                                           lkind = kind_of(latom)
     705        55388 :                                           rik(1) = dcnum(iatom)%rik(1, i)
     706        55388 :                                           rik(2) = dcnum(iatom)%rik(2, i)
     707        55388 :                                           rik(3) = dcnum(iatom)%rik(3, i)
     708        55388 :                                           drk = SQRT(rik(1)*rik(1) + rik(2)*rik(2) + rik(3)*rik(3))
     709       221552 :                                           fdik(:) = -de922*dcnum(iatom)%dvals(i)*rik(:)/drk
     710        55388 :                                           atom_d = atom_of_kind(latom)
     711       221552 :                                           force(ikind)%dispersion(:, atom_a) = force(ikind)%dispersion(:, atom_a) - fdik(:)
     712       221552 :                                           force(lkind)%dispersion(:, atom_d) = force(lkind)%dispersion(:, atom_d) + fdik(:)
     713        69354 :                                           IF (use_virial) THEN
     714        55224 :                                              CALL virial_pair_force(pv_virial_thread, -1._dp, fdik, rik)
     715              :                                           END IF
     716              :                                        END DO
     717              :                                     END IF
     718              : 
     719              :                                  END IF
     720              : 
     721              :                               END IF
     722              :                            END DO
     723              :                         END DO
     724              :                      END DO
     725              :                   END DO
     726              : 
     727              :                END IF
     728              :             END IF
     729              :          END IF
     730              :       END DO
     731              : 
     732        72280 :       virial%pv_virial = virial%pv_virial + pv_virial_thread
     733              : 
     734         5560 :       CALL neighbor_list_iterator_release(nl_iterator)
     735              : 
     736         5560 :       elrc6 = 0._dp
     737         5560 :       elrc8 = 0._dp
     738         5560 :       elrc9 = 0._dp
     739              :       ! Long range correction (atomic contributions not implemented)
     740         5560 :       IF (dispersion_env%lrc) THEN
     741          120 :          ALLOCATE (cnkind(nkind))
     742           40 :          cnkind = 0._dp
     743              :          ! first use the default values
     744           90 :          DO ikind = 1, nkind
     745           50 :             CALL get_atomic_kind(atomic_kind_set(ikind), z=za)
     746           90 :             cnkind(ikind) = dispersion_env%cn(za)
     747              :          END DO
     748              :          ! now check for changes from default
     749           40 :          IF (ASSOCIATED(dispersion_env%cnkind)) THEN
     750           12 :             DO i = 1, SIZE(dispersion_env%cnkind)
     751            6 :                ikind = dispersion_env%cnkind(i)%kind
     752           12 :                cnkind(ikind) = dispersion_env%cnkind(i)%cnum
     753              :             END DO
     754              :          END IF
     755           90 :          DO ikind = 1, nkind
     756           50 :             CALL get_atomic_kind(atomic_kind_set(ikind), natom=na, z=za)
     757           50 :             CALL get_qs_kind(qs_kind_set(ikind), dispersion=disp_a, ghost=ghost_a, floating=floating_a)
     758           50 :             IF (.NOT. disp_a%defined .OR. ghost_a .OR. floating_a) CYCLE
     759          204 :             DO jkind = 1, nkind
     760           66 :                CALL get_atomic_kind(atomic_kind_set(jkind), natom=nb, z=zb)
     761           66 :                CALL get_qs_kind(qs_kind_set(jkind), dispersion=disp_b, ghost=ghost_b, floating=floating_b)
     762           66 :                IF (.NOT. disp_b%defined .OR. ghost_b .OR. floating_b) CYCLE
     763           64 :                IF (dispersion_env%nd3_exclude_pair > 0) THEN
     764              :                   CALL exclude_d3_kind_pair(dispersion_env%d3_exclude_pair, ikind, jkind, &
     765            8 :                                             exclude=exclude_pair)
     766            8 :                   IF (exclude_pair) CYCLE
     767              :                END IF
     768              :                CALL getc6(maxc, max_elem, dispersion_env%c6ab, dispersion_env%maxci, za, zb, &
     769           58 :                           cnkind(ikind), cnkind(jkind), dispersion_env%k3, cc6ab, dcc6aba, dcc6abb)
     770           58 :                elrc6 = elrc6 - s6*twopi*REAL(na*nb, KIND=dp)*cc6ab/(3._dp*rcut**3*cell%deth)
     771           58 :                c8 = 3.0d0*cc6ab*dispersion_env%r2r4(za)*dispersion_env%r2r4(zb)
     772           58 :                elrc8 = elrc8 - s8*twopi*REAL(na*nb, KIND=dp)*c8/(5._dp*rcut**5*cell%deth)
     773          174 :                IF (dispersion_env%doabc) THEN
     774          144 :                   DO kkind = 1, nkind
     775           86 :                      CALL get_atomic_kind(atomic_kind_set(kkind), natom=nc, z=zc)
     776           86 :                      CALL get_qs_kind(qs_kind_set(kkind), dispersion=disp_c, ghost=ghost_c, floating=floating_c)
     777           86 :                      IF (.NOT. disp_c%defined .OR. ghost_c .OR. floating_c) CYCLE
     778           84 :                      IF (dispersion_env%nd3_exclude_pair > 0) THEN
     779              :                         CALL exclude_d3_kind_pair(dispersion_env%d3_exclude_pair, ikind, jkind, kkind, &
     780            4 :                                                   exclude_pair)
     781            4 :                         IF (exclude_pair) CYCLE
     782              :                      END IF
     783              :                      CALL getc6(maxc, max_elem, dispersion_env%c6ab, dispersion_env%maxci, za, zb, &
     784           82 :                                 cnkind(ikind), cnkind(jkind), dispersion_env%k3, cc6ab, dcc6aba, dcc6abb)
     785              :                      CALL getc6(maxc, max_elem, dispersion_env%c6ab, dispersion_env%maxci, zc, za, &
     786           82 :                                 cnkind(kkind), cnkind(ikind), dispersion_env%k3, cc6ca, dcc6aba, dcc6abb)
     787              :                      CALL getc6(maxc, max_elem, dispersion_env%c6ab, dispersion_env%maxci, zb, zc, &
     788           82 :                                 cnkind(jkind), cnkind(kkind), dispersion_env%k3, cc6bc, dcc6aba, dcc6abb)
     789           82 :                      c9 = -SQRT(cc6ab*cc6bc*cc6ca)
     790          226 :                      elrc9 = elrc9 - s9*64._dp*twopi*REAL(na*nb*nc, KIND=dp)*c9/(6._dp*rcut**3*cell%deth**2)
     791              :                   END DO
     792              :                END IF
     793              :             END DO
     794              :          END DO
     795           40 :          IF (use_virial) THEN
     796           26 :             IF (para_env%is_source()) THEN
     797           52 :                DO i = 1, 3
     798           52 :                   virial%pv_virial(i, i) = virial%pv_virial(i, i) + (elrc6 + elrc8 + 2._dp*elrc9)
     799              :                END DO
     800              :             END IF
     801              :          END IF
     802           40 :          DEALLOCATE (cnkind)
     803              :       END IF
     804              : 
     805         5560 :       DEALLOCATE (cnumbers)
     806         5560 :       IF (dispersion_env%doabc .AND. dispersion_env%c9cnst) THEN
     807           66 :          DEALLOCATE (cnumfix)
     808              :       END IF
     809         5560 :       IF (calculate_forces .OR. debugall) THEN
     810        10690 :          DO iatom = 1, natom
     811        10690 :             DEALLOCATE (dcnum(iatom)%nlist, dcnum(iatom)%dvals, dcnum(iatom)%rik)
     812              :          END DO
     813          814 :          DEALLOCATE (dcnum)
     814              :       ELSE
     815         4746 :          DEALLOCATE (dcnum)
     816              :       END IF
     817              : 
     818              :       ! set dispersion energy
     819              : 
     820         5560 :       CALL para_env%sum(e6tot)
     821         5560 :       CALL para_env%sum(e8tot)
     822         5560 :       CALL para_env%sum(e9tot)
     823         5560 :       CALL para_env%sum(evdw)
     824         5560 :       CALL para_env%sum(nab)
     825         5560 :       CALL para_env%sum(nabc)
     826         5560 :       e6tot = e6tot + elrc6
     827         5560 :       e8tot = e8tot + elrc8
     828         5560 :       e9tot = e9tot + elrc9
     829              :       ! For printing, we need all contributions
     830         5560 :       evdw = evdw + (elrc6 + elrc8 + elrc9)
     831         5560 :       IF (unit_nr > 0) THEN
     832           45 :          WRITE (unit_nr, "(A,F20.0)") "  E6 vdW terms              :", nab
     833           45 :          WRITE (unit_nr, *) " E6 vdW energy [au/kcal]   :", e6tot, e6tot*kcalmol
     834           45 :          WRITE (unit_nr, *) " E8 vdW energy [au/kcal]   :", e8tot, e8tot*kcalmol
     835           45 :          WRITE (unit_nr, *) " %E8 on total vdW energy   :", e8tot/evdw*100._dp
     836           45 :          WRITE (unit_nr, "(A,F20.0)") "  E9 vdW terms              :", nabc
     837           45 :          WRITE (unit_nr, *) " E9 vdW energy [au/kcal]   :", e9tot, e9tot*kcalmol
     838           45 :          WRITE (unit_nr, *) " %E9 on total vdW energy   :", e9tot/evdw*100._dp
     839           45 :          IF (dispersion_env%lrc) THEN
     840            1 :             WRITE (unit_nr, *) " E LRC C6 [au/kcal]        :", elrc6, elrc6*kcalmol
     841            1 :             WRITE (unit_nr, *) " E LRC C8 [au/kcal]        :", elrc8, elrc8*kcalmol
     842            1 :             WRITE (unit_nr, *) " E LRC C9 [au/kcal]        :", elrc9, elrc9*kcalmol
     843              :          END IF
     844              :       END IF
     845              : 
     846         5560 :       evdw = evdw/para_env%num_pe
     847              : 
     848         5560 :       DEALLOCATE (dodisp, exclude, atomnumber, rcpbc, radd2, c6d2)
     849              : 
     850         5560 :       IF (domol) THEN
     851            2 :          DEALLOCATE (atom2mol)
     852              :       END IF
     853              : 
     854         5560 :       CALL timestop(handle)
     855              : 
     856        11120 :    END SUBROUTINE calculate_dispersion_d3_pairpot
     857              : 
     858              : ! **************************************************************************************************
     859              : !> \brief ...
     860              : !> \param c6ab ...
     861              : !> \param maxci ...
     862              : !> \param filename ...
     863              : !> \param para_env ...
     864              : ! **************************************************************************************************
     865          466 :    SUBROUTINE dftd3_c6_param(c6ab, maxci, filename, para_env)
     866              : 
     867              :       REAL(KIND=dp), DIMENSION(:, :, :, :, :)            :: c6ab
     868              :       INTEGER, DIMENSION(:)                              :: maxci
     869              :       CHARACTER(LEN=*)                                   :: filename
     870              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     871              : 
     872              :       INTEGER                                            :: funit, iadr, iat, jadr, jat, kk, nl, &
     873              :                                                             nlines, nn, ref_stride
     874          466 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: pars
     875              : 
     876          466 :       IF (para_env%is_source()) THEN
     877              :          ! Read the DFT-D3 C6AB parameters from file "filename"
     878          238 :          CALL open_file(file_name=filename, unit_number=funit, file_form="FORMATTED")
     879          238 :          READ (funit, *) nl, nlines
     880              :       END IF
     881          466 :       CALL para_env%bcast(nl)
     882          466 :       CALL para_env%bcast(nlines)
     883         1398 :       ALLOCATE (pars(nl))
     884          466 :       IF (para_env%is_source()) THEN
     885          238 :          READ (funit, *) pars(1:nl)
     886          238 :          CALL close_file(unit_number=funit)
     887              :       END IF
     888          466 :       CALL para_env%bcast(pars)
     889              : 
     890              : ! Store C6AB coefficients in an array
     891    733873576 :       c6ab = -1._dp
     892        48464 :       maxci = 0
     893          466 :       ref_stride = get_ref_stride(pars, nlines)
     894          466 :       kk = 1
     895     26698072 :       DO nn = 1, nlines
     896     26697606 :          iat = NINT(pars(kk + 1))
     897     26697606 :          jat = NINT(pars(kk + 2))
     898     26697606 :          CALL limit(iat, jat, iadr, jadr, ref_stride)
     899     26697606 :          maxci(iat) = MAX(maxci(iat), iadr)
     900     26697606 :          maxci(jat) = MAX(maxci(jat), jadr)
     901     26697606 :          c6ab(iat, jat, iadr, jadr, 1) = pars(kk)
     902     26697606 :          c6ab(iat, jat, iadr, jadr, 2) = pars(kk + 3)
     903     26697606 :          c6ab(iat, jat, iadr, jadr, 3) = pars(kk + 4)
     904              : 
     905     26697606 :          c6ab(jat, iat, jadr, iadr, 1) = pars(kk)
     906     26697606 :          c6ab(jat, iat, jadr, iadr, 2) = pars(kk + 4)
     907     26697606 :          c6ab(jat, iat, jadr, iadr, 3) = pars(kk + 3)
     908     26698072 :          kk = (nn*5) + 1
     909              :       END DO
     910              : 
     911          466 :       DEALLOCATE (pars)
     912              : 
     913          466 :    END SUBROUTINE dftd3_c6_param
     914              : 
     915              : ! **************************************************************************************************
     916              : !> \brief Detects the reference-state encoding used in the DFT-D3 C6AB table.
     917              : !> \param pars DFT-D3 C6AB parameter table.
     918              : !> \param nlines Number of C6AB parameter lines.
     919              : !> \return Reference-state stride.
     920              : ! **************************************************************************************************
     921          466 :    FUNCTION get_ref_stride(pars, nlines) RESULT(ref_stride)
     922              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: pars
     923              :       INTEGER, INTENT(IN)                                :: nlines
     924              :       INTEGER                                            :: ref_stride
     925              : 
     926              :       INTEGER                                            :: kk, nn
     927              : 
     928          466 :       ref_stride = 100
     929          466 :       kk = 1
     930      2496362 :       DO nn = 1, nlines
     931      2496362 :          IF (NINT(pars(kk + 1)) > 1000 .OR. NINT(pars(kk + 2)) > 1000) THEN
     932              :             ref_stride = 1000
     933              :             EXIT
     934              :          END IF
     935      2495896 :          kk = (nn*5) + 1
     936              :       END DO
     937              : 
     938          466 :    END FUNCTION get_ref_stride
     939              : 
     940              : ! **************************************************************************************************
     941              : !> \brief Decodes element numbers and reference-state indices.
     942              : !> \param iat Encoded first element number.
     943              : !> \param jat Encoded second element number.
     944              : !> \param iadr First reference-state index.
     945              : !> \param jadr Second reference-state index.
     946              : !> \param ref_stride Reference-state stride.
     947              : ! **************************************************************************************************
     948     26697606 :    SUBROUTINE limit(iat, jat, iadr, jadr, ref_stride)
     949              :       INTEGER                                            :: iat, jat, iadr, jadr, ref_stride
     950              : 
     951     26697606 :       iadr = 1
     952     26697606 :       jadr = 1
     953     89391382 :       DO WHILE (iat > ref_stride)
     954     62693776 :          iat = iat - ref_stride
     955     89391382 :          iadr = iadr + 1
     956              :       END DO
     957              : 
     958     45992336 :       DO WHILE (jat > ref_stride)
     959     19294730 :          jat = jat - ref_stride
     960     19294730 :          jadr = jadr + 1
     961              :       END DO
     962     26697606 :    END SUBROUTINE limit
     963              : 
     964              : ! **************************************************************************************************
     965              : !> \brief ...
     966              : !> \param rab ...
     967              : !> \param rcutab ...
     968              : !> \param srn ...
     969              : !> \param alpn ...
     970              : !> \param rcut ...
     971              : !> \param fdab ...
     972              : !> \param dfdab ...
     973              : ! **************************************************************************************************
     974      7835118 :    SUBROUTINE damping_d3(rab, rcutab, srn, alpn, rcut, fdab, dfdab)
     975              : 
     976              :       REAL(KIND=dp), INTENT(IN)                          :: rab, rcutab, srn, alpn, rcut
     977              :       REAL(KIND=dp), INTENT(OUT)                         :: fdab, dfdab
     978              : 
     979              :       REAL(KIND=dp)                                      :: a, b, c, d, dd, dfab, dfcc, dz, fab, &
     980              :                                                             fcc, rl, rr, ru, z, zz
     981              : 
     982      7835118 :       rl = rcut - 1._dp
     983      7835118 :       ru = rcut
     984      7835118 :       IF (rab >= ru) THEN
     985              :          fcc = 0._dp
     986              :          dfcc = 0._dp
     987      7835118 :       ELSEIF (rab <= rl) THEN
     988              :          fcc = 1._dp
     989              :          dfcc = 0._dp
     990              :       ELSE
     991       712728 :          z = rab*rab - rl*rl
     992       712728 :          dz = 2._dp*rab
     993       712728 :          zz = z*z*z
     994       712728 :          d = ru*ru - rl*rl
     995       712728 :          dd = d*d*d
     996       712728 :          a = -10._dp/dd
     997       712728 :          b = 15._dp/(dd*d)
     998       712728 :          c = -6._dp/(dd*d*d)
     999       712728 :          fcc = 1._dp + zz*(a + b*z + c*z*z)
    1000       712728 :          dfcc = zz*dz/z*(3._dp*a + 4._dp*b*z + 5._dp*c*z*z)
    1001              :       END IF
    1002              : 
    1003      7835118 :       rr = 6._dp*(rab/(srn*rcutab))**(-alpn)
    1004      7835118 :       fab = 1._dp/(1._dp + rr)
    1005      7835118 :       dfab = fab*fab*rr*alpn/rab
    1006      7835118 :       fdab = fab*fcc
    1007      7835118 :       dfdab = dfab*fcc + fab*dfcc
    1008              : 
    1009      7835118 :    END SUBROUTINE damping_d3
    1010              : 
    1011              : ! **************************************************************************************************
    1012              : !> \brief ...
    1013              : !> \param maxc ...
    1014              : !> \param max_elem ...
    1015              : !> \param c6ab ...
    1016              : !> \param mxc ...
    1017              : !> \param iat ...
    1018              : !> \param jat ...
    1019              : !> \param nci ...
    1020              : !> \param ncj ...
    1021              : !> \param k3 ...
    1022              : !> \param c6 ...
    1023              : !> \param dc6a ...
    1024              : !> \param dc6b ...
    1025              : ! **************************************************************************************************
    1026      9019758 :    SUBROUTINE getc6(maxc, max_elem, c6ab, mxc, iat, jat, nci, ncj, k3, c6, dc6a, dc6b)
    1027              : 
    1028              :       INTEGER, INTENT(IN)                                :: maxc, max_elem
    1029              :       REAL(KIND=dp), INTENT(IN) :: c6ab(max_elem, max_elem, maxc, maxc, 3)
    1030              :       INTEGER, INTENT(IN)                                :: mxc(max_elem), iat, jat
    1031              :       REAL(KIND=dp), INTENT(IN)                          :: nci, ncj, k3
    1032              :       REAL(KIND=dp), INTENT(OUT)                         :: c6, dc6a, dc6b
    1033              : 
    1034              :       INTEGER                                            :: i, j
    1035              :       REAL(KIND=dp)                                      :: c6mem, cn1, cn2, csum, dtmpa, dtmpb, &
    1036              :                                                             dwa, dwb, dza, dzb, r, rsave, rsum, &
    1037              :                                                             tmp1
    1038              : 
    1039              : ! the exponential is sensitive to numerics
    1040              : ! when nci or ncj is much larger than cn1/cn2
    1041              : 
    1042      9019758 :       c6mem = -1.0e+99_dp
    1043      9019758 :       rsave = 1.0e+99_dp
    1044      9019758 :       rsum = 0.0_dp
    1045      9019758 :       csum = 0.0_dp
    1046      9019758 :       dza = 0.0_dp
    1047      9019758 :       dzb = 0.0_dp
    1048      9019758 :       dwa = 0.0_dp
    1049      9019758 :       dwb = 0.0_dp
    1050      9019758 :       c6 = 0.0_dp
    1051     33117414 :       DO i = 1, mxc(iat)
    1052    103390894 :          DO j = 1, mxc(jat)
    1053     70273480 :             c6 = c6ab(iat, jat, i, j, 1)
    1054     94371136 :             IF (c6 > 0.0_dp) THEN
    1055     70273480 :                cn1 = c6ab(iat, jat, i, j, 2)
    1056     70273480 :                cn2 = c6ab(iat, jat, i, j, 3)
    1057              :                ! distance
    1058     70273480 :                r = (cn1 - nci)**2 + (cn2 - ncj)**2
    1059     70273480 :                IF (r < rsave) THEN
    1060     35061600 :                   rsave = r
    1061     35061600 :                   c6mem = c6
    1062              :                END IF
    1063     70273480 :                tmp1 = EXP(k3*r)
    1064     70273480 :                dtmpa = -2.0_dp*k3*(cn1 - nci)*tmp1
    1065     70273480 :                dtmpb = -2.0_dp*k3*(cn2 - ncj)*tmp1
    1066     70273480 :                rsum = rsum + tmp1
    1067     70273480 :                csum = csum + tmp1*c6
    1068     70273480 :                dza = dza + dtmpa*c6
    1069     70273480 :                dwa = dwa + dtmpa
    1070     70273480 :                dzb = dzb + dtmpb*c6
    1071     70273480 :                dwb = dwb + dtmpb
    1072              :             END IF
    1073              :          END DO
    1074              :       END DO
    1075              : 
    1076      9019758 :       IF (c6 == 0.0_dp) c6mem = 0.0_dp
    1077              : 
    1078      9019758 :       IF (rsum > 1.0e-66_dp) THEN
    1079      9005390 :          c6 = csum/rsum
    1080      9005390 :          dc6a = (dza - c6*dwa)/rsum
    1081      9005390 :          dc6b = (dzb - c6*dwb)/rsum
    1082              :       ELSE
    1083        14368 :          c6 = c6mem
    1084        14368 :          dc6a = 0._dp
    1085        14368 :          dc6b = 0._dp
    1086              :       END IF
    1087              : 
    1088      9019758 :    END SUBROUTINE getc6
    1089              : 
    1090              : END MODULE qs_dispersion_d3
        

Generated by: LCOV version 2.0-1