LCOV - code coverage report
Current view: top level - src - qs_dispersion_pairpot.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 84.7 % 262 222
Test Date: 2026-11-04 00:58:17 Functions: 100.0 % 2 2

            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 dispersion using pair potentials
      10              : !> \author JGH
      11              : ! **************************************************************************************************
      12              : MODULE qs_dispersion_pairpot
      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 bibliography,                    ONLY: &
      20              :         Caldeweyher2017, Caldeweyher2019, Caldeweyher2020, Chai2008, Goerigk2017, Wittmann2024, &
      21              :         cite_reference, grimme2006, grimme2010, grimme2011
      22              :    USE cell_types,                      ONLY: cell_type
      23              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      24              :                                               cp_logger_get_default_io_unit,&
      25              :                                               cp_logger_type
      26              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      27              :                                               cp_print_key_unit_nr
      28              :    USE cp_parser_methods,               ONLY: parser_get_next_line,&
      29              :                                               parser_get_object
      30              :    USE cp_parser_types,                 ONLY: cp_parser_type,&
      31              :                                               parser_create,&
      32              :                                               parser_release
      33              :    USE eeq_input,                       ONLY: read_eeq_param
      34              :    USE input_constants,                 ONLY: vdw_pairpot_dftd2,&
      35              :                                               vdw_pairpot_dftd2chg,&
      36              :                                               vdw_pairpot_dftd3,&
      37              :                                               vdw_pairpot_dftd3bj,&
      38              :                                               vdw_pairpot_dftd4,&
      39              :                                               xc_vdw_fun_pairpot
      40              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      41              :                                               section_vals_type,&
      42              :                                               section_vals_val_get
      43              :    USE kinds,                           ONLY: default_path_length,&
      44              :                                               default_string_length,&
      45              :                                               dp
      46              :    USE message_passing,                 ONLY: mp_para_env_type
      47              :    USE physcon,                         ONLY: bohr,&
      48              :                                               kcalmol,&
      49              :                                               kjmol
      50              :    USE qs_dispersion_cnum,              ONLY: get_cn_radius,&
      51              :                                               setcn,&
      52              :                                               seten,&
      53              :                                               setr0ab,&
      54              :                                               setrcov
      55              :    USE qs_dispersion_d2,                ONLY: calculate_dispersion_d2_pairpot,&
      56              :                                               dftd2_param
      57              :    USE qs_dispersion_d3,                ONLY: calculate_dispersion_d3_pairpot,&
      58              :                                               dftd3_c6_param
      59              :    USE qs_dispersion_d4,                ONLY: calculate_dispersion_d4_pairpot
      60              :    USE qs_dispersion_s_dftd3,           ONLY: dftd3_param_from_library
      61              :    USE qs_dispersion_types,             ONLY: dftd2_pp,&
      62              :                                               dftd3_pp,&
      63              :                                               dftd4_pp,&
      64              :                                               qs_atom_dispersion_type,&
      65              :                                               qs_dispersion_type
      66              :    USE qs_environment_types,            ONLY: get_qs_env,&
      67              :                                               qs_environment_type
      68              :    USE qs_force_types,                  ONLY: qs_force_type
      69              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      70              :                                               qs_kind_type,&
      71              :                                               set_qs_kind
      72              :    USE virial_types,                    ONLY: virial_type
      73              : #include "./base/base_uses.f90"
      74              : 
      75              :    IMPLICIT NONE
      76              : 
      77              :    PRIVATE
      78              : 
      79              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_dispersion_pairpot'
      80              : 
      81              :    PUBLIC :: qs_dispersion_pairpot_init, calculate_dispersion_pairpot
      82              : 
      83              : ! **************************************************************************************************
      84              : 
      85              : CONTAINS
      86              : 
      87              : ! **************************************************************************************************
      88              : !> \brief ...
      89              : !> \param atomic_kind_set ...
      90              : !> \param qs_kind_set ...
      91              : !> \param dispersion_env ...
      92              : !> \param pp_section ...
      93              : !> \param para_env ...
      94              : ! **************************************************************************************************
      95         1312 :    SUBROUTINE qs_dispersion_pairpot_init(atomic_kind_set, qs_kind_set, dispersion_env, pp_section, para_env)
      96              :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
      97              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
      98              :       TYPE(qs_dispersion_type), POINTER                  :: dispersion_env
      99              :       TYPE(section_vals_type), OPTIONAL, POINTER         :: pp_section
     100              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     101              : 
     102              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_dispersion_pairpot_init'
     103              : 
     104              :       CHARACTER(LEN=2)                                   :: symbol
     105              :       CHARACTER(LEN=default_path_length)                 :: filename
     106              :       CHARACTER(LEN=default_string_length)               :: aname, error_msg
     107              :       CHARACTER(LEN=default_string_length), &
     108         1312 :          DIMENSION(:), POINTER                           :: tmpstringlist
     109              :       INTEGER                                            :: elem, handle, i, ikind, j, max_elem, &
     110              :                                                             maxc, n_rep, nkind, nl, vdw_pp_type, &
     111              :                                                             vdw_type
     112         1312 :       INTEGER, DIMENSION(:), POINTER                     :: exlist
     113              :       LOGICAL                                            :: at_end, explicit, found, is_available
     114              :       REAL(KIND=dp)                                      :: dum
     115              :       TYPE(qs_atom_dispersion_type), POINTER             :: disp
     116              :       TYPE(section_vals_type), POINTER                   :: eeq_section
     117              : 
     118         1312 :       CALL timeset(routineN, handle)
     119              : 
     120         1312 :       nkind = SIZE(atomic_kind_set)
     121              : 
     122         1312 :       vdw_type = dispersion_env%type
     123         1312 :       SELECT CASE (vdw_type)
     124              :       CASE DEFAULT
     125              :          ! do nothing
     126              :       CASE (xc_vdw_fun_pairpot)
     127              :          ! setup information on pair potentials
     128         1312 :          vdw_pp_type = dispersion_env%type
     129         1312 :          SELECT CASE (dispersion_env%pp_type)
     130              :          CASE DEFAULT
     131              :             ! do nothing
     132              :          CASE (vdw_pairpot_dftd2, vdw_pairpot_dftd2chg)
     133           38 :             CALL cite_reference(Grimme2006)
     134           38 :             IF (dispersion_env%pp_type == vdw_pairpot_dftd2chg) CALL cite_reference(Chai2008)
     135          108 :             DO ikind = 1, nkind
     136           70 :                CALL get_atomic_kind(atomic_kind_set(ikind), element_symbol=symbol, z=elem)
     137           70 :                ALLOCATE (disp)
     138           70 :                disp%type = dftd2_pp
     139              :                ! get filename of parameter file
     140           70 :                filename = dispersion_env%parameter_file_name
     141              :                ! check for local parameters
     142           70 :                found = .FALSE.
     143           70 :                IF (PRESENT(pp_section)) THEN
     144           64 :                   CALL section_vals_val_get(pp_section, "ATOMPARM", n_rep_val=n_rep)
     145           64 :                   DO i = 1, n_rep
     146              :                      CALL section_vals_val_get(pp_section, "ATOMPARM", i_rep_val=i, &
     147            0 :                                                c_vals=tmpstringlist)
     148           64 :                      IF (TRIM(tmpstringlist(1)) == TRIM(symbol)) THEN
     149              :                         ! we assume the parameters are in atomic units!
     150            0 :                         READ (tmpstringlist(2), *) disp%c6
     151            0 :                         READ (tmpstringlist(3), *) disp%vdw_radii
     152            0 :                         found = .TRUE.
     153            0 :                         EXIT
     154              :                      END IF
     155              :                   END DO
     156              :                END IF
     157           70 :                IF (.NOT. found) THEN
     158              :                   ! check for internal parameters
     159           70 :                   CALL dftd2_param(elem, disp%c6, disp%vdw_radii, found)
     160              :                END IF
     161           70 :                IF (.NOT. found) THEN
     162              :                   ! check on file
     163            0 :                   INQUIRE (FILE=filename, EXIST=is_available)
     164            0 :                   IF (is_available) THEN
     165            0 :                      BLOCK
     166              :                         TYPE(cp_parser_type) :: parser
     167            0 :                         CALL parser_create(parser, filename, para_env=para_env)
     168              :                         DO
     169              :                            at_end = .FALSE.
     170            0 :                            CALL parser_get_next_line(parser, 1, at_end)
     171            0 :                            IF (at_end) EXIT
     172            0 :                            CALL parser_get_object(parser, aname)
     173            0 :                            IF (TRIM(aname) == TRIM(symbol)) THEN
     174            0 :                               CALL parser_get_object(parser, disp%c6)
     175              :                               ! we have to change the units J*nm^6*mol^-1 -> Hartree*Bohr^6
     176            0 :                               disp%c6 = disp%c6*1000._dp*bohr**6/kjmol
     177            0 :                               CALL parser_get_object(parser, disp%vdw_radii)
     178            0 :                               disp%vdw_radii = disp%vdw_radii*bohr
     179            0 :                               found = .TRUE.
     180            0 :                               EXIT
     181              :                            END IF
     182              :                         END DO
     183            0 :                         CALL parser_release(parser)
     184              :                      END BLOCK
     185              :                   END IF
     186              :                END IF
     187           70 :                IF (found) THEN
     188           70 :                   disp%defined = .TRUE.
     189              :                ELSE
     190            0 :                   disp%defined = .FALSE.
     191              :                END IF
     192              :                ! Check if the parameter is defined
     193           70 :                IF (.NOT. disp%defined) THEN
     194              :                   CALL cp_abort(__LOCATION__, &
     195              :                                 "Dispersion parameters for element ("//TRIM(symbol)//") are not defined! "// &
     196              :                                 "Please provide a valid set of parameters through the input section or "// &
     197            0 :                                 "through an external file! ")
     198              :                END IF
     199          178 :                CALL set_qs_kind(qs_kind_set(ikind), dispersion=disp)
     200              :             END DO
     201              :          CASE (vdw_pairpot_dftd3, vdw_pairpot_dftd3bj)
     202              :             !DFT-D3 Method initial setup
     203          584 :             CALL cite_reference(Grimme2010)
     204          584 :             CALL cite_reference(Grimme2011)
     205          584 :             CALL cite_reference(Goerigk2017)
     206          584 :             CALL cite_reference(Wittmann2024)
     207          584 :             max_elem = 103
     208          584 :             maxc = 7
     209          584 :             dispersion_env%max_elem = max_elem
     210          584 :             dispersion_env%maxc = maxc
     211          584 :             ALLOCATE (dispersion_env%maxci(max_elem))
     212          584 :             ALLOCATE (dispersion_env%c6ab(max_elem, max_elem, maxc, maxc, 3))
     213          584 :             ALLOCATE (dispersion_env%r0ab(max_elem, max_elem))
     214          584 :             ALLOCATE (dispersion_env%rcov(max_elem))
     215          584 :             ALLOCATE (dispersion_env%eneg(max_elem))
     216          584 :             ALLOCATE (dispersion_env%r2r4(max_elem))
     217          584 :             ALLOCATE (dispersion_env%cn(max_elem))
     218              : 
     219          584 :             IF (dispersion_env%d3_reference_code) THEN
     220              :                CALL dftd3_param_from_library(dispersion_env%c6ab, dispersion_env%maxci, &
     221              :                                              dispersion_env%r0ab, dispersion_env%rcov, &
     222              :                                              dispersion_env%r2r4, &
     223              :                                              dispersion_env%pp_type, dispersion_env%ref_functional, &
     224              :                                              dispersion_env%s6, dispersion_env%s8, &
     225              :                                              dispersion_env%a1, dispersion_env%a2, &
     226              :                                              dispersion_env%sr6, dispersion_env%sr8, &
     227              :                                              para_env, error=error_msg, &
     228           52 :                                              calc_scaling=.NOT. dispersion_env%d3_scaling_explicit)
     229           52 :                IF (error_msg /= "") THEN
     230            0 :                   CALL cp_abort(__LOCATION__, error_msg)
     231              :                END IF
     232              :             ELSE
     233          532 :                filename = dispersion_env%parameter_file_name
     234          532 :                CALL dftd3_c6_param(dispersion_env%c6ab, dispersion_env%maxci, filename, para_env)
     235          532 :                CALL setrcov(dispersion_env%rcov)
     236          532 :                CALL setr0ab(dispersion_env%r0ab, dispersion_env%rcov, dispersion_env%r2r4)
     237              :             END IF
     238              :             ! Electronegativity
     239          584 :             CALL seten(dispersion_env%eneg)
     240              :             ! the default coordination numbers
     241          584 :             CALL setcn(dispersion_env%cn)
     242              :             ! scale r4/r2 values of the atoms by sqrt(Z)
     243              :             ! sqrt is also globally close to optimum
     244              :             ! together with the factor 1/2 this yield reasonable
     245              :             ! c8 for he, ne and ar. for larger Z, C8 becomes too large
     246              :             ! which effectively mimics higher R^n terms neglected due
     247              :             ! to stability reasons
     248          584 :             IF (.NOT. dispersion_env%d3_reference_code) THEN
     249        55328 :                DO i = 1, max_elem
     250        54796 :                   dum = 0.5_dp*dispersion_env%r2r4(i)*REAL(i, dp)**0.5_dp
     251              :                   ! store it as sqrt because the geom. av. is taken
     252        55328 :                   dispersion_env%r2r4(i) = SQRT(dum)
     253              :                END DO
     254              :             END IF
     255              :             ! parameters
     256          584 :             dispersion_env%k1 = 16.0_dp
     257          584 :             dispersion_env%k2 = 4._dp/3._dp
     258              :             ! reasonable choices are between 3 and 5
     259              :             ! this gives smoth curves with maxima around the integer values
     260              :             ! k3=3 give for CN=0 a slightly smaller value than computed
     261              :             ! for the free atom. This also yields to larger CN for atoms
     262              :             ! in larger molecules but with the same chem. environment
     263              :             ! which is physically not right
     264              :             ! values >5 might lead to bumps in the potential
     265          584 :             dispersion_env%k3 = -4._dp
     266          584 :             IF (.NOT. dispersion_env%d3_reference_code) THEN
     267        55328 :                dispersion_env%rcov = dispersion_env%k2*dispersion_env%rcov*bohr
     268              :             END IF
     269              :             ! alpha default parameter
     270          584 :             dispersion_env%alp = 14._dp
     271              :             !
     272         1844 :             DO ikind = 1, nkind
     273         1260 :                CALL get_atomic_kind(atomic_kind_set(ikind), element_symbol=symbol, z=elem)
     274         1260 :                ALLOCATE (disp)
     275         1260 :                disp%type = dftd3_pp
     276         1260 :                IF (elem <= max_elem) THEN
     277         1260 :                   disp%defined = .TRUE.
     278              :                ELSE
     279              :                   disp%defined = .FALSE.
     280              :                END IF
     281         1260 :                IF (.NOT. disp%defined) THEN
     282              :                   CALL cp_abort(__LOCATION__, &
     283              :                                 "Dispersion parameters for element ("//TRIM(symbol)//") are not defined! "// &
     284              :                                 "Please provide a valid set of parameters through the input section or "// &
     285            0 :                                 "through an external file! ")
     286              :                END IF
     287         3104 :                CALL set_qs_kind(qs_kind_set(ikind), dispersion=disp)
     288              :             END DO
     289              : 
     290          584 :             IF (PRESENT(pp_section)) THEN
     291              :                ! Check for coordination numbers
     292          170 :                CALL section_vals_val_get(pp_section, "KIND_COORDINATION_NUMBERS", n_rep_val=n_rep)
     293          170 :                IF (n_rep > 0) THEN
     294           32 :                   ALLOCATE (dispersion_env%cnkind(n_rep))
     295           16 :                   DO i = 1, n_rep
     296              :                      CALL section_vals_val_get(pp_section, "KIND_COORDINATION_NUMBERS", i_rep_val=i, &
     297            8 :                                                c_vals=tmpstringlist)
     298            8 :                      READ (tmpstringlist(1), *) dispersion_env%cnkind(i)%cnum
     299           16 :                      READ (tmpstringlist(2), *) dispersion_env%cnkind(i)%kind
     300              :                   END DO
     301              :                END IF
     302          170 :                CALL section_vals_val_get(pp_section, "ATOM_COORDINATION_NUMBERS", n_rep_val=n_rep)
     303          170 :                IF (n_rep > 0) THEN
     304           10 :                   ALLOCATE (dispersion_env%cnlist(n_rep))
     305            6 :                   DO i = 1, n_rep
     306              :                      CALL section_vals_val_get(pp_section, "ATOM_COORDINATION_NUMBERS", i_rep_val=i, &
     307            4 :                                                c_vals=tmpstringlist)
     308            4 :                      nl = SIZE(tmpstringlist)
     309           12 :                      ALLOCATE (dispersion_env%cnlist(i)%atom(nl - 1))
     310            4 :                      dispersion_env%cnlist(i)%natom = nl - 1
     311            4 :                      READ (tmpstringlist(1), *) dispersion_env%cnlist(i)%cnum
     312           14 :                      DO j = 1, nl - 1
     313           12 :                         READ (tmpstringlist(j + 1), *) dispersion_env%cnlist(i)%atom(j)
     314              :                      END DO
     315              :                   END DO
     316              :                END IF
     317              :                ! Check for exclusion lists
     318          170 :                CALL section_vals_val_get(pp_section, "D3_EXCLUDE_KIND", explicit=explicit)
     319          170 :                IF (explicit) THEN
     320            2 :                   CALL section_vals_val_get(pp_section, "D3_EXCLUDE_KIND", i_vals=exlist)
     321            4 :                   DO j = 1, SIZE(exlist)
     322            2 :                      ikind = exlist(j)
     323            2 :                      CALL get_qs_kind(qs_kind_set(ikind), dispersion=disp)
     324            4 :                      disp%defined = .FALSE.
     325              :                   END DO
     326              :                END IF
     327          170 :                CALL section_vals_val_get(pp_section, "D3_EXCLUDE_KIND_PAIR", n_rep_val=n_rep)
     328          170 :                dispersion_env%nd3_exclude_pair = n_rep
     329          170 :                IF (n_rep > 0) THEN
     330            6 :                   ALLOCATE (dispersion_env%d3_exclude_pair(n_rep, 2))
     331            6 :                   DO i = 1, n_rep
     332              :                      CALL section_vals_val_get(pp_section, "D3_EXCLUDE_KIND_PAIR", i_rep_val=i, &
     333            4 :                                                i_vals=exlist)
     334           22 :                      dispersion_env%d3_exclude_pair(i, :) = exlist
     335              :                   END DO
     336              :                END IF
     337              :             END IF
     338              :          CASE (vdw_pairpot_dftd4)
     339              :             !most checks are done by the library
     340          690 :             CALL cite_reference(Caldeweyher2017)
     341          690 :             CALL cite_reference(Caldeweyher2019)
     342          690 :             CALL cite_reference(Caldeweyher2020)
     343         2150 :             DO ikind = 1, nkind
     344         1460 :                CALL get_atomic_kind(atomic_kind_set(ikind), element_symbol=symbol, z=elem)
     345         1460 :                ALLOCATE (disp)
     346         1460 :                disp%type = dftd4_pp
     347         1460 :                disp%defined = .TRUE.
     348         3610 :                CALL set_qs_kind(qs_kind_set(ikind), dispersion=disp)
     349              :             END DO
     350              :             ! maybe needed in cnumber calculations
     351          690 :             max_elem = 103
     352          690 :             maxc = 7
     353          690 :             dispersion_env%max_elem = max_elem
     354          690 :             dispersion_env%maxc = maxc
     355          690 :             ALLOCATE (dispersion_env%maxci(max_elem))
     356          690 :             ALLOCATE (dispersion_env%rcov(max_elem))
     357          690 :             ALLOCATE (dispersion_env%eneg(max_elem))
     358          690 :             ALLOCATE (dispersion_env%cn(max_elem))
     359              :             ! the default covalent radii
     360          690 :             CALL setrcov(dispersion_env%rcov)
     361              :             ! the default coordination numbers
     362          690 :             CALL setcn(dispersion_env%cn)
     363              :             ! Electronegativity
     364          690 :             CALL seten(dispersion_env%eneg)
     365              :             ! parameters
     366          690 :             dispersion_env%k1 = 16.0_dp
     367          690 :             dispersion_env%k2 = 4._dp/3._dp
     368          690 :             dispersion_env%k3 = -4._dp
     369        71760 :             dispersion_env%rcov = dispersion_env%k2*dispersion_env%rcov*bohr
     370          690 :             dispersion_env%alp = 14._dp
     371              :             !
     372          690 :             dispersion_env%cnfun = 3
     373          690 :             IF (dispersion_env%rc_cn < 0.0_dp) THEN
     374          690 :                dispersion_env%rc_cn = get_cn_radius(dispersion_env)
     375              :             END IF
     376         2002 :             IF (PRESENT(pp_section)) THEN
     377           48 :                eeq_section => section_vals_get_subs_vals(pp_section, "EEQ")
     378           48 :                CALL read_eeq_param(eeq_section, dispersion_env%eeq_sparam)
     379              :             END IF
     380              :          END SELECT
     381              :       END SELECT
     382              : 
     383         1312 :       CALL timestop(handle)
     384              : 
     385         1312 :    END SUBROUTINE qs_dispersion_pairpot_init
     386              : 
     387              : ! **************************************************************************************************
     388              : !> \brief ...
     389              : !> \param qs_env ...
     390              : !> \param dispersion_env ...
     391              : !> \param energy ...
     392              : !> \param calculate_forces ...
     393              : !> \param atevdw ...
     394              : ! **************************************************************************************************
     395        26040 :    SUBROUTINE calculate_dispersion_pairpot(qs_env, dispersion_env, energy, calculate_forces, atevdw)
     396              : 
     397              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     398              :       TYPE(qs_dispersion_type), POINTER                  :: dispersion_env
     399              :       REAL(KIND=dp), INTENT(INOUT)                       :: energy
     400              :       LOGICAL, INTENT(IN)                                :: calculate_forces
     401              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL              :: atevdw
     402              : 
     403              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_dispersion_pairpot'
     404              : 
     405              :       INTEGER                                            :: atom_a, handle, iatom, ikind, iw, natom, &
     406              :                                                             nkind, unit_nr
     407        26040 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind, kind_of
     408              :       LOGICAL                                            :: atenergy, atex, debugall, use_virial
     409              :       REAL(KIND=dp)                                      :: evdw, gnorm
     410        26040 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: atomic_energy
     411              :       REAL(KIND=dp), DIMENSION(3)                        :: fdij
     412              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: dvirial, pv_loc, pv_virial_thread
     413        26040 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     414              :       TYPE(atprop_type), POINTER                         :: atprop
     415              :       TYPE(cell_type), POINTER                           :: cell
     416              :       TYPE(cp_logger_type), POINTER                      :: logger
     417              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     418        26040 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
     419              :       TYPE(virial_type), POINTER                         :: virial
     420              : 
     421        26040 :       energy = 0._dp
     422              :       ! make valgrind happy
     423        26040 :       use_virial = .FALSE.
     424              : 
     425        26040 :       IF (dispersion_env%type /= xc_vdw_fun_pairpot) THEN
     426              :          RETURN
     427              :       END IF
     428              : 
     429         6816 :       CALL timeset(routineN, handle)
     430              : 
     431         6816 :       NULLIFY (atomic_kind_set)
     432              : 
     433              :       CALL get_qs_env(qs_env=qs_env, nkind=nkind, natom=natom, atomic_kind_set=atomic_kind_set, &
     434         6816 :                       cell=cell, virial=virial, para_env=para_env, atprop=atprop)
     435              : 
     436         6816 :       debugall = dispersion_env%verbose
     437              : 
     438         6816 :       NULLIFY (logger)
     439         6816 :       logger => cp_get_default_logger()
     440         6816 :       IF (ASSOCIATED(dispersion_env%dftd_section)) THEN
     441              :          unit_nr = cp_print_key_unit_nr(logger, dispersion_env%dftd_section, "PRINT_DFTD", &
     442          412 :                                         extension=".dftd")
     443              :       ELSE
     444         6404 :          unit_nr = -1
     445              :       END IF
     446              : 
     447              :       ! atomic energy and stress arrays
     448         6816 :       atenergy = atprop%energy
     449              :       ! external atomic energy
     450         6816 :       atex = .FALSE.
     451         6816 :       IF (PRESENT(atevdw)) THEN
     452            2 :          atex = .TRUE.
     453              :       END IF
     454              : 
     455         6816 :       IF (unit_nr > 0) THEN
     456           68 :          WRITE (unit_nr, *)
     457           68 :          WRITE (unit_nr, *) " Pair potential vdW calculation"
     458           68 :          IF (dispersion_env%pp_type == vdw_pairpot_dftd2) THEN
     459            7 :             WRITE (unit_nr, *) " Dispersion potential type: DFT-D2"
     460            7 :             WRITE (unit_nr, *) " Scaling parameter (s6) ", dispersion_env%scaling
     461            7 :             WRITE (unit_nr, *) " Exponential prefactor  ", dispersion_env%exp_pre
     462              :          ELSE IF (dispersion_env%pp_type == vdw_pairpot_dftd2chg) THEN
     463            0 :             WRITE (unit_nr, *) " Dispersion potential type: DFT-D2(CHG)"
     464            0 :             WRITE (unit_nr, *) " Scaling parameter (s6) ", dispersion_env%scaling
     465            0 :             WRITE (unit_nr, *) " CHG damping: a=6, alpha=12"
     466              :          ELSE IF (dispersion_env%pp_type == vdw_pairpot_dftd3) THEN
     467           20 :             WRITE (unit_nr, *) " Dispersion potential type: DFT-D3"
     468              :          ELSE IF (dispersion_env%pp_type == vdw_pairpot_dftd3bj) THEN
     469           25 :             WRITE (unit_nr, *) " Dispersion potential type: DFT-D3(BJ)"
     470              :          ELSE IF (dispersion_env%pp_type == vdw_pairpot_dftd4) THEN
     471           16 :             WRITE (unit_nr, *) " Dispersion potential type: DFT-D4"
     472              :          END IF
     473              :       END IF
     474              : 
     475         6816 :       CALL get_qs_env(qs_env=qs_env, force=force)
     476         6816 :       use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
     477          786 :       IF (use_virial .AND. debugall) THEN
     478          130 :          dvirial = virial%pv_virial
     479              :       END IF
     480         6816 :       IF (use_virial) THEN
     481        10218 :          pv_loc = virial%pv_virial
     482              :       END IF
     483              : 
     484         6816 :       evdw = 0._dp
     485              :       pv_virial_thread(:, :) = 0._dp
     486              : 
     487         6816 :       CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind, kind_of=kind_of)
     488              : 
     489         6816 :       IF (dispersion_env%pp_type == vdw_pairpot_dftd2 .OR. &
     490              :           dispersion_env%pp_type == vdw_pairpot_dftd2chg) THEN
     491          148 :          CALL calculate_dispersion_d2_pairpot(qs_env, dispersion_env, evdw, calculate_forces, atevdw)
     492         6742 :       ELSE IF (dispersion_env%pp_type == vdw_pairpot_dftd3 .OR. &
     493              :                dispersion_env%pp_type == vdw_pairpot_dftd3bj) THEN
     494              :          CALL calculate_dispersion_d3_pairpot(qs_env, dispersion_env, evdw, calculate_forces, &
     495        11642 :                                               unit_nr, atevdw)
     496          920 :       ELSE IF (dispersion_env%pp_type == vdw_pairpot_dftd4) THEN
     497          920 :          IF (dispersion_env%lrc) THEN
     498            0 :             CPABORT("Long range correction with DFTD4 not implemented")
     499              :          END IF
     500          920 :          IF (dispersion_env%srb) THEN
     501            0 :             CPABORT("Short range bond correction with DFTD4 not implemented")
     502              :          END IF
     503          920 :          IF (dispersion_env%domol) THEN
     504            0 :             CPABORT("Molecular approximation with DFTD4 not implemented")
     505              :          END IF
     506              :          !
     507          920 :          iw = -1
     508          920 :          IF (dispersion_env%verbose) iw = cp_logger_get_default_io_unit(logger)
     509              :          !
     510          920 :          IF (atenergy .OR. atex) THEN
     511            0 :             ALLOCATE (atomic_energy(natom))
     512              :             CALL calculate_dispersion_d4_pairpot(qs_env, dispersion_env, evdw, calculate_forces, &
     513            0 :                                                  iw, atomic_energy=atomic_energy)
     514              :          ELSE
     515          920 :             CALL calculate_dispersion_d4_pairpot(qs_env, dispersion_env, evdw, calculate_forces, iw)
     516              :          END IF
     517              :          !
     518          920 :          IF (atex) THEN
     519            0 :             atevdw(1:natom) = atomic_energy(1:natom)
     520              :          END IF
     521          920 :          IF (atenergy) THEN
     522            0 :             CALL atprop_array_init(atprop%atevdw, natom)
     523            0 :             atprop%atevdw(1:natom) = atomic_energy(1:natom)
     524              :          END IF
     525          920 :          IF (atenergy .OR. atex) THEN
     526            0 :             DEALLOCATE (atomic_energy)
     527              :          END IF
     528              :       END IF
     529              : 
     530              :       ! set dispersion energy
     531         6816 :       CALL para_env%sum(evdw)
     532         6816 :       energy = evdw
     533         6816 :       IF (unit_nr > 0) THEN
     534           68 :          WRITE (unit_nr, *) " Total vdW energy [au]     :", evdw
     535           68 :          WRITE (unit_nr, *) " Total vdW energy [kcal]   :", evdw*kcalmol
     536           68 :          WRITE (unit_nr, *)
     537              :       END IF
     538         6816 :       IF (calculate_forces .AND. debugall) THEN
     539           44 :          IF (unit_nr > 0) THEN
     540            1 :             WRITE (unit_nr, *) " Dispersion Forces         "
     541            1 :             WRITE (unit_nr, *) " Atom   Kind                            Forces    "
     542              :          END IF
     543           44 :          gnorm = 0._dp
     544          236 :          DO iatom = 1, natom
     545          192 :             ikind = kind_of(iatom)
     546          192 :             atom_a = atom_of_kind(iatom)
     547          768 :             fdij(1:3) = force(ikind)%dispersion(:, atom_a)
     548          192 :             CALL para_env%sum(fdij)
     549          768 :             gnorm = gnorm + SUM(ABS(fdij))
     550          236 :             IF (unit_nr > 0) WRITE (unit_nr, "(i5,i7,3F20.14)") iatom, ikind, fdij
     551              :          END DO
     552           44 :          IF (unit_nr > 0) THEN
     553            1 :             WRITE (unit_nr, *)
     554            1 :             WRITE (unit_nr, *) "|G| = ", gnorm
     555            1 :             WRITE (unit_nr, *)
     556              :          END IF
     557           44 :          IF (use_virial) THEN
     558          104 :             dvirial = virial%pv_virial - dvirial
     559            8 :             CALL para_env%sum(dvirial)
     560            8 :             IF (unit_nr > 0) THEN
     561            0 :                WRITE (unit_nr, *) "Stress Tensor (dispersion)"
     562            0 :                WRITE (unit_nr, "(3G20.12)") dvirial
     563            0 :                WRITE (unit_nr, *) "  Tr(P)/3 :  ", (dvirial(1, 1) + dvirial(2, 2) + dvirial(3, 3))/3._dp
     564            0 :                WRITE (unit_nr, *)
     565              :             END IF
     566              :          END IF
     567              :       END IF
     568              : 
     569         6816 :       IF (calculate_forces .AND. use_virial) THEN
     570         4004 :          virial%pv_vdw = virial%pv_vdw + (virial%pv_virial - pv_loc)
     571              :       END IF
     572              : 
     573         6816 :       IF (ASSOCIATED(dispersion_env%dftd_section)) THEN
     574          412 :          CALL cp_print_key_finished_output(unit_nr, logger, dispersion_env%dftd_section, "PRINT_DFTD")
     575              :       END IF
     576              : 
     577         6816 :       CALL timestop(handle)
     578              : 
     579        32856 :    END SUBROUTINE calculate_dispersion_pairpot
     580              : 
     581              : END MODULE qs_dispersion_pairpot
        

Generated by: LCOV version 2.0-1