LCOV - code coverage report
Current view: top level - src - manybody_ace.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:dc5a454) Lines: 86 87 98.9 %
Date: 2025-06-17 07:40:17 Functions: 3 3 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \par History
      10             : !>      HAF (16-Apr-2025) : Import into CP2K
      11             : !> \author HAF and yury-lysogorskiy and ralf-drautz
      12             : ! **************************************************************************************************
      13             : 
      14             : MODULE manybody_ace
      15             : 
      16             :    USE ISO_C_BINDING,                   ONLY: C_ASSOCIATED
      17             :    USE ace_nlist,                       ONLY: ace_interface
      18             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      19             :                                               get_atomic_kind
      20             :    USE bibliography,                    ONLY: Bochkarev2024,&
      21             :                                               Drautz2019,&
      22             :                                               Lysogorskiy2021,&
      23             :                                               cite_reference
      24             :    USE cell_types,                      ONLY: cell_type
      25             :    USE fist_nonbond_env_types,          ONLY: ace_data_type,&
      26             :                                               fist_nonbond_env_get,&
      27             :                                               fist_nonbond_env_set,&
      28             :                                               fist_nonbond_env_type
      29             :    USE kinds,                           ONLY: dp
      30             :    USE pair_potential_types,            ONLY: ace_type,&
      31             :                                               pair_potential_pp_type,&
      32             :                                               pair_potential_single_type
      33             :    USE particle_types,                  ONLY: particle_type
      34             :    USE physcon,                         ONLY: angstrom,&
      35             :                                               evolt
      36             : #include "./base/base_uses.f90"
      37             : 
      38             :    IMPLICIT NONE
      39             : 
      40             :    PRIVATE
      41             :    PUBLIC ace_energy_store_force_virial, ace_add_force_virial
      42             : 
      43             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'manybody_ace'
      44             : 
      45             : CONTAINS
      46             : 
      47             : ! **************************************************************************************************
      48             : !> \brief ...
      49             : !> \param particle_set ...
      50             : !> \param atomic_kind_set ...
      51             : !> \param potparm ...
      52             : !> \param ace_data ...
      53             : ! **************************************************************************************************
      54           6 :    SUBROUTINE init_ace_data(particle_set, atomic_kind_set, potparm, &
      55             :                             ace_data)
      56             : 
      57             :       TYPE(particle_type), POINTER                       :: particle_set(:)
      58             :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind_set(:)
      59             :       TYPE(pair_potential_pp_type), POINTER              :: potparm
      60             :       TYPE(ace_data_type), POINTER                       :: ace_data
      61             : 
      62             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'init_ace_data'
      63             : 
      64             :       CHARACTER(2)                                       :: element_symbol
      65             :       INTEGER                                            :: ace_natom, handle, i, iat, iat_use, &
      66             :                                                             ikind, jkind, lkind, n_atoms
      67           6 :       INTEGER, ALLOCATABLE                               :: use_atom_type(:)
      68           6 :       INTEGER, DIMENSION(:), POINTER                     :: ak_alist
      69           6 :       LOGICAL, ALLOCATABLE                               :: use_atom(:)
      70             :       TYPE(pair_potential_single_type), POINTER          :: pot
      71             : 
      72           6 :       CALL timeset(routineN, handle)
      73             : 
      74             :       ! init ace_data
      75           6 :       IF (.NOT. ASSOCIATED(ace_data)) THEN
      76           0 :          ALLOCATE (ace_data)
      77             :       END IF
      78             : 
      79           6 :       n_atoms = SIZE(particle_set)
      80          18 :       ALLOCATE (use_atom(n_atoms))
      81          12 :       ALLOCATE (use_atom_type(n_atoms))
      82         996 :       use_atom = .FALSE.
      83         996 :       use_atom_type = 0
      84             : 
      85          18 :       DO ikind = 1, SIZE(atomic_kind_set)
      86          12 :          pot => potparm%pot(ikind, ikind)%pot
      87          30 :          DO i = 1, SIZE(pot%type)
      88          12 :             IF (pot%type(i) /= ace_type) CYCLE
      89             :             CALL get_atomic_kind(atomic_kind=atomic_kind_set(ikind), &
      90             :                                  element_symbol=element_symbol, &
      91          12 :                                  natom=lkind, atom_list=ak_alist)
      92          12 :             IF (lkind < 1) CYCLE
      93          12 :             ace_data%model = pot%set(i)%ace%model
      94          12 :             jkind = 0
      95          18 :             DO iat = 1, SIZE(ace_data%model%symbolc)
      96          18 :                IF (element_symbol == ace_data%model%symbolc(iat)) THEN
      97             :                   jkind = iat
      98             :                   EXIT
      99             :                END IF
     100             :             END DO
     101          12 :             CPASSERT(jkind > 0)
     102        1026 :             DO iat = 1, lkind
     103         990 :                use_atom_type(ak_alist(iat)) = jkind
     104        1002 :                use_atom(ak_alist(iat)) = .TRUE.
     105             :             END DO
     106             :          END DO ! i
     107             :       END DO ! ikind
     108           6 :       CPASSERT(C_ASSOCIATED(ace_data%model%c_ptr))
     109             : 
     110         996 :       ace_natom = COUNT(use_atom)
     111             : 
     112           6 :       IF (.NOT. ALLOCATED(ace_data%uctype)) THEN
     113          18 :          ALLOCATE (ace_data%uctype(1:ace_natom))
     114             :       END IF
     115             : 
     116             :       iat_use = 0
     117         996 :       DO iat = 1, n_atoms
     118         990 :          IF (.NOT. use_atom(iat)) CYCLE
     119         990 :          iat_use = iat_use + 1
     120         996 :          ace_data%uctype(iat_use) = use_atom_type(iat)
     121             :       END DO
     122             : 
     123           6 :       IF (iat_use > 0) THEN
     124           6 :          CALL cite_reference(Drautz2019)
     125           6 :          CALL cite_reference(Lysogorskiy2021)
     126           6 :          CALL cite_reference(Bochkarev2024)
     127             :       END IF
     128             : 
     129           6 :       IF (.NOT. ALLOCATED(ace_data%force)) THEN
     130          18 :          ALLOCATE (ace_data%force(3, ace_natom))
     131          18 :          ALLOCATE (ace_data%use_indices(ace_natom))
     132          12 :          ALLOCATE (ace_data%inverse_index_map(n_atoms))
     133             :       END IF
     134           6 :       CPASSERT(SIZE(ace_data%force, 2) == ace_natom)
     135             : 
     136           6 :       iat_use = 0
     137         996 :       ace_data%inverse_index_map(:) = 0
     138         996 :       DO iat = 1, n_atoms
     139         996 :          IF (use_atom(iat)) THEN
     140         990 :             iat_use = iat_use + 1
     141         990 :             ace_data%use_indices(iat_use) = iat
     142         990 :             ace_data%inverse_index_map(iat) = iat_use
     143             :          END IF
     144             :       END DO
     145           6 :       ace_data%natom = ace_natom
     146           6 :       DEALLOCATE (use_atom, use_atom_type)
     147             : 
     148           6 :       CALL timestop(handle)
     149             : 
     150           6 :    END SUBROUTINE init_ace_data
     151             : 
     152             : ! **************************************************************************************************
     153             : !> \brief ...
     154             : !>     > \param particle_set ...
     155             : !> \param particle_set ...
     156             : !> \param cell ...
     157             : !> \param atomic_kind_set ...
     158             : !> \param potparm ...
     159             : !> \param fist_nonbond_env ...
     160             : !> \param pot_ace ...
     161             : ! **************************************************************************************************
     162         412 :    SUBROUTINE ace_energy_store_force_virial(particle_set, cell, atomic_kind_set, potparm, &
     163             :                                             fist_nonbond_env, pot_ace)
     164             : 
     165             :       TYPE(particle_type), POINTER                       :: particle_set(:)
     166             :       TYPE(cell_type), POINTER                           :: cell
     167             :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind_set(:)
     168             :       TYPE(pair_potential_pp_type), POINTER              :: potparm
     169             :       TYPE(fist_nonbond_env_type), POINTER               :: fist_nonbond_env
     170             :       REAL(kind=dp), INTENT(OUT)                         :: pot_ace
     171             : 
     172             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'ace_energy_store_force_virial'
     173             : 
     174             :       INTEGER                                            :: handle
     175             :       REAL(kind=dp)                                      :: ace_virial(1:6)
     176             :       TYPE(ace_data_type), POINTER                       :: ace_data
     177             : 
     178         206 :       CALL timeset(routineN, handle)
     179             : 
     180             :       ! get ace_data to save force, virial info
     181         206 :       CALL fist_nonbond_env_get(fist_nonbond_env, ace_data=ace_data)
     182         206 :       IF (.NOT. ASSOCIATED(ace_data)) THEN
     183          84 :          ALLOCATE (ace_data)
     184             :          !initialize ace_data:
     185           6 :          CALL init_ace_data(particle_set, atomic_kind_set, potparm, ace_data)
     186           6 :          CALL fist_nonbond_env_set(fist_nonbond_env, ace_data=ace_data)
     187             :       END IF
     188             : 
     189             :       CALL ace_interface(ace_data%natom, ace_data%uctype, &
     190             :                          pot_ace, ace_data%force, ace_virial, &
     191         206 :                          fist_nonbond_env, cell, ace_data)
     192             : 
     193             :       ! convert units
     194         206 :       pot_ace = pot_ace/evolt
     195      157766 :       ace_data%force = ace_data%force/(evolt/angstrom)
     196        1442 :       ace_virial = ace_virial/evolt
     197             : 
     198             :       ! minus sign due to CP2K conventions
     199         206 :       ace_data%virial(1, 1) = -ace_virial(1)
     200         206 :       ace_data%virial(2, 2) = -ace_virial(2)
     201         206 :       ace_data%virial(3, 3) = -ace_virial(3)
     202         206 :       ace_data%virial(1, 2) = -ace_virial(4)
     203         206 :       ace_data%virial(2, 1) = -ace_virial(4)
     204         206 :       ace_data%virial(1, 3) = -ace_virial(5)
     205         206 :       ace_data%virial(3, 1) = -ace_virial(5)
     206         206 :       ace_data%virial(2, 3) = -ace_virial(6)
     207         206 :       ace_data%virial(3, 2) = -ace_virial(6)
     208             : 
     209         206 :       CALL timestop(handle)
     210         206 :    END SUBROUTINE ace_energy_store_force_virial
     211             : 
     212             : ! **************************************************************************************************
     213             : !> \brief ...
     214             : !> \param fist_nonbond_env ...
     215             : !> \param force ...
     216             : !> \param pv_nonbond ...
     217             : !> \param use_virial ...
     218             : ! **************************************************************************************************
     219         206 :    SUBROUTINE ace_add_force_virial(fist_nonbond_env, force, pv_nonbond, use_virial)
     220             :       TYPE(fist_nonbond_env_type), POINTER               :: fist_nonbond_env
     221             :       REAL(KIND=dp), INTENT(INOUT)                       :: force(:, :), pv_nonbond(3, 3)
     222             :       LOGICAL, OPTIONAL                                  :: use_virial
     223             : 
     224             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'ace_add_force_virial'
     225             : 
     226             :       INTEGER                                            :: handle, iat, iat_use
     227             :       TYPE(ace_data_type), POINTER                       :: ace_data
     228             : 
     229         206 :       CALL timeset(routineN, handle)
     230             : 
     231         206 :       CALL fist_nonbond_env_get(fist_nonbond_env, ace_data=ace_data)
     232             : 
     233         206 :       IF (.NOT. ASSOCIATED(ace_data)) RETURN
     234             : 
     235       39596 :       DO iat_use = 1, SIZE(ace_data%use_indices)
     236       39390 :          iat = ace_data%use_indices(iat_use)
     237       39390 :          CPASSERT(iat >= 1 .AND. iat <= SIZE(force, 2))
     238      157766 :          force(1:3, iat) = force(1:3, iat) + ace_data%force(1:3, iat_use)
     239             :       END DO
     240             : 
     241         206 :       IF (use_virial) THEN
     242          26 :          pv_nonbond = pv_nonbond + ace_data%virial
     243             :       END IF
     244             : 
     245         206 :       CALL timestop(handle)
     246             :    END SUBROUTINE ace_add_force_virial
     247             : 
     248             : END MODULE manybody_ace

Generated by: LCOV version 1.15