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

Generated by: LCOV version 2.0-1