LCOV - code coverage report
Current view: top level - src - ace_nlist.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 100.0 % 102 102
Test Date: 2025-12-04 06:27:48 Functions: 100.0 % 1 1

            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 ace_nlist
      15              : 
      16              :    USE ace_wrapper,                     ONLY: ace_model_compute
      17              :    USE cell_types,                      ONLY: cell_type
      18              :    USE fist_neighbor_list_types,        ONLY: fist_neighbor_type,&
      19              :                                               neighbor_kind_pairs_type
      20              :    USE fist_nonbond_env_types,          ONLY: ace_data_type,&
      21              :                                               fist_nonbond_env_get,&
      22              :                                               fist_nonbond_env_type,&
      23              :                                               pos_type
      24              :    USE kinds,                           ONLY: dp
      25              :    USE physcon,                         ONLY: angstrom
      26              : #include "./base/base_uses.f90"
      27              : 
      28              :    IMPLICIT NONE
      29              : 
      30              :    PRIVATE
      31              :    PUBLIC ace_interface
      32              : 
      33              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ace_nlist'
      34              : 
      35              : CONTAINS
      36              : 
      37              : !
      38              : !-------------------------------------------------------------------------------------
      39              : 
      40              : ! **************************************************************************************************
      41              : !> \brief ...
      42              : !> \param ace_natom ...
      43              : !> \param ace_atype ...
      44              : !> \param pot_ace ...
      45              : !> \param ace_force ...
      46              : !> \param ace_virial ...
      47              : !> \param fist_nonbond_env ...
      48              : !> \param cell ...
      49              : !> \param ace_data ...
      50              : ! **************************************************************************************************
      51          206 :    SUBROUTINE ace_interface(ace_natom, ace_atype, pot_ace, ace_force, ace_virial, &
      52              :                             fist_nonbond_env, cell, ace_data)
      53              : 
      54              :       INTEGER, INTENT(IN)                                :: ace_natom, ace_atype(1:ace_natom)
      55              :       REAL(kind=dp), INTENT(OUT)                         :: pot_ace, ace_force(1:3, 1:ace_natom), &
      56              :                                                             ace_virial(1:6)
      57              :       TYPE(fist_nonbond_env_type), POINTER               :: fist_nonbond_env
      58              :       TYPE(cell_type), POINTER                           :: cell
      59              :       TYPE(ace_data_type), POINTER                       :: ace_data
      60              : 
      61              : #if defined(__ACE)
      62              :       INTEGER                                            :: atom_a, atom_b, counter, ilist, k, m, n, &
      63              :                                                             natom, nghost, num_update
      64          206 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: ghostidx, listidx
      65          206 :       REAL(KIND=8), ALLOCATABLE                          :: forceunroll(:)
      66          412 :       REAL(kind=dp)                                      :: cell_v(3), dv(1:3), energy(1:ace_natom)
      67              :       TYPE(fist_neighbor_type), POINTER                  :: nonbonded
      68              :       TYPE(neighbor_kind_pairs_type), POINTER            :: neighbor_kind_pair
      69          206 :       TYPE(pos_type), DIMENSION(:), POINTER              :: r_last_update_pbc
      70              : 
      71          206 :       natom = ace_natom
      72              : 
      73              :       CALL fist_nonbond_env_get(fist_nonbond_env, nonbonded=nonbonded, &
      74              :                                 r_last_update_pbc=r_last_update_pbc, &
      75          206 :                                 num_update=num_update, counter=counter)
      76              : 
      77          206 :       IF ((counter == 1) .OR. (ace_data%refupdate /= num_update)) THEN
      78              :          ! fist neighborlist are new:
      79           14 :          ace_data%refupdate = num_update
      80              : 
      81           14 :          IF (.NOT. ALLOCATED(ace_data%neiat)) THEN
      82           18 :             ALLOCATE (ace_data%neiat(0:natom))
      83              :          ELSE
      84            8 :             CPASSERT(SIZE(ace_data%neiat) > natom)
      85              :          END IF
      86              : 
      87              :          !if more than one mpi task, some neighorlists might be empty
      88              :          !do we need to check for lone atoms?
      89           56 :          ALLOCATE (ghostidx(natom), listidx(natom))
      90           14 :          nghost = 0
      91         2554 :          ace_data%neiat(:) = 0
      92           14 :          ace_data%nei = 0
      93         1796 :          DO n = 1, SIZE(nonbonded%neighbor_kind_pairs)
      94         1782 :             neighbor_kind_pair => nonbonded%neighbor_kind_pairs(n)
      95         1796 :             IF (neighbor_kind_pair%npairs > 0) THEN
      96              :                IF ((neighbor_kind_pair%cell_vector(1) == 0) .AND. &
      97          439 :                    (neighbor_kind_pair%cell_vector(2) == 0) .AND. &
      98              :                    (neighbor_kind_pair%cell_vector(3) == 0)) THEN
      99         2540 :                   DO ilist = 1, natom
     100         2540 :                      ghostidx(ilist) = ilist
     101              :                   END DO
     102              :                ELSE
     103        66284 :                   ghostidx = 0
     104              :                END IF
     105       282151 :                DO ilist = 1, neighbor_kind_pair%npairs
     106       281712 :                   atom_a = ace_data%inverse_index_map(neighbor_kind_pair%list(1, ilist))
     107       281712 :                   atom_b = ace_data%inverse_index_map(neighbor_kind_pair%list(2, ilist))
     108       281712 :                   IF ((atom_a == 0) .OR. (atom_b == 0)) CYCLE
     109       281712 :                   ace_data%neiat(atom_a) = ace_data%neiat(atom_a) + 1
     110       282151 :                   IF (ghostidx(atom_b) == 0) THEN
     111              :                      ! new ghost
     112        15930 :                      nghost = nghost + 1
     113        15930 :                      ghostidx(atom_b) = nghost + natom
     114              :                   END IF
     115              :                END DO
     116              :             END IF
     117              :          END DO
     118              :          ! build running sum
     119         2540 :          DO n = 1, natom
     120         2540 :             ace_data%neiat(n) = ace_data%neiat(n) + ace_data%neiat(n - 1)
     121              :          END DO
     122           14 :          ace_data%nei = ace_data%neiat(natom)
     123           14 :          ace_data%nghost = nghost
     124              : 
     125           14 :          IF (ALLOCATED(ace_data%nlist)) THEN
     126            8 :             IF (SIZE(ace_data%nlist) < ace_data%nei) THEN
     127            2 :                DEALLOCATE (ace_data%nlist)
     128            6 :                ALLOCATE (ace_data%nlist(1:ace_data%nei))
     129              :             END IF
     130              :          ELSE
     131           18 :             ALLOCATE (ace_data%nlist(1:ace_data%nei))
     132              :          END IF
     133              : 
     134           14 :          IF (ALLOCATED(ace_data%attype)) THEN
     135            8 :             IF (SIZE(ace_data%attype) < natom + nghost) THEN
     136            3 :                DEALLOCATE (ace_data%atpos)
     137            3 :                DEALLOCATE (ace_data%attype)
     138            3 :                DEALLOCATE (ace_data%origin)
     139            3 :                DEALLOCATE (ace_data%shift)
     140            9 :                ALLOCATE (ace_data%atpos(1:3, 1:natom + nghost))
     141            9 :                ALLOCATE (ace_data%attype(1:natom + nghost))
     142            6 :                ALLOCATE (ace_data%origin(1:natom + nghost))
     143            9 :                ALLOCATE (ace_data%shift(1:3, 1:natom + nghost))
     144              :             END IF
     145              :          ELSE
     146           18 :             ALLOCATE (ace_data%atpos(1:3, 1:natom + nghost))
     147           18 :             ALLOCATE (ace_data%attype(1:natom + nghost))
     148           12 :             ALLOCATE (ace_data%origin(1:natom + nghost))
     149           18 :             ALLOCATE (ace_data%shift(1:3, 1:natom + nghost))
     150              :          END IF
     151         2540 :          ace_data%attype(1:natom) = ace_atype(:)
     152              : 
     153         2540 :          DO n = 1, natom
     154        20208 :             ace_data%atpos(:, n) = r_last_update_pbc(ace_data%use_indices(n))%r*angstrom
     155         2540 :             ace_data%origin(n) = n
     156              :          END DO
     157        74222 :          ace_data%shift(:, :) = 0
     158              : 
     159           14 :          k = natom
     160         2540 :          listidx(1:natom) = ace_data%neiat(0:natom - 1)
     161         1796 :          DO n = 1, SIZE(nonbonded%neighbor_kind_pairs)
     162         1782 :             neighbor_kind_pair => nonbonded%neighbor_kind_pairs(n)
     163         1796 :             IF (neighbor_kind_pair%npairs > 0) THEN
     164              :                IF ((neighbor_kind_pair%cell_vector(1) == 0) .AND. &
     165          439 :                    (neighbor_kind_pair%cell_vector(2) == 0) .AND. &
     166              :                    (neighbor_kind_pair%cell_vector(3) == 0)) THEN
     167         2540 :                   DO m = 1, natom
     168         2540 :                      ghostidx(m) = m
     169              :                   END DO
     170              :                ELSE
     171        66284 :                   ghostidx = 0
     172              :                END IF
     173         1756 :                dv = REAL(neighbor_kind_pair%cell_vector, KIND=dp)
     174              :                ! dimensions it's not periodic with should be zero in cell_vector
     175              :                ! so should always be valid:
     176         7463 :                cell_v = MATMUL(cell%hmat, dv)*angstrom
     177       282151 :                DO ilist = 1, neighbor_kind_pair%npairs
     178       281712 :                   atom_a = ace_data%inverse_index_map(neighbor_kind_pair%list(1, ilist))
     179       281712 :                   atom_b = ace_data%inverse_index_map(neighbor_kind_pair%list(2, ilist))
     180       281712 :                   IF ((atom_a == 0) .OR. (atom_b == 0)) CYCLE
     181       281712 :                   IF (ghostidx(atom_b) == 0) THEN
     182        15930 :                      k = k + 1
     183        63720 :                      ace_data%atpos(:, k) = ace_data%atpos(:, atom_b) + cell_v
     184       127440 :                      ace_data%shift(:, k) = neighbor_kind_pair%cell_vector
     185        15930 :                      ace_data%origin(k) = atom_b
     186        15930 :                      ace_data%attype(k) = ace_atype(atom_b)
     187        15930 :                      ghostidx(atom_b) = k
     188              :                   END IF
     189       281712 :                   listidx(atom_a) = listidx(atom_a) + 1
     190       282151 :                   ace_data%nlist(listidx(atom_a)) = ghostidx(atom_b)
     191              :                END DO
     192              :             END IF
     193              :          END DO
     194              : 
     195           14 :          DEALLOCATE (ghostidx)
     196           14 :          DEALLOCATE (listidx)
     197              : 
     198              : !         transforming to c call
     199              : !     -> atom index will change from 1...n to 0...n-1 -> subtract 1 from neighborlist
     200       281726 :          ace_data%nlist(1:ace_data%nei) = ace_data%nlist(1:ace_data%nei) - 1
     201        18470 :          ace_data%origin(1:natom + nghost) = ace_data%origin(1:natom + nghost) - 1
     202              : !-----------------------------------------------
     203              : 
     204              :       ELSE ! no changes in neighbor list just update positions:
     205          192 :          nghost = ace_data%nghost
     206        37056 :          DO n = 1, natom
     207       295104 :             ace_data%atpos(:, n) = r_last_update_pbc(ace_data%use_indices(n))%r*angstrom
     208              :          END DO
     209       236023 :          DO n = natom + 1, natom + nghost
     210       943324 :             dv = REAL(ace_data%shift(:, n), KIND=dp)*angstrom
     211              :             !origin+1 since we already changed to C notation for origin:
     212      3773488 :             ace_data%atpos(:, n) = ace_data%atpos(:, ace_data%origin(n) + 1) + MATMUL(cell%hmat, dv)
     213              :          END DO
     214              :       END IF
     215              : 
     216              : ! -> force array
     217          618 :       ALLOCATE (forceunroll(1:3*natom))
     218       118376 :       forceunroll = 0.0
     219          206 :       pot_ace = 0.0
     220          206 :       ace_virial = 0.0
     221              : 
     222              :       CALL ace_model_compute( &
     223              :          natomc=natom, &
     224              :          nghostc=nghost, &
     225              :          neic=ace_data%nei, &
     226              :          neiatc=ace_data%neiat, &
     227              :          originc=ace_data%origin, &
     228              :          nlistc=ace_data%nlist, &
     229              :          attypec=ace_data%attype, &
     230              :          atposc=RESHAPE(ace_data%atpos, [3*(natom + nghost)]), &
     231              :          forcec=forceunroll, &
     232              :          virialc=ace_virial, &
     233              :          energyc=energy, &
     234          412 :          model=ace_data%model)
     235              : 
     236          618 :       ace_force = RESHAPE(forceunroll, [3, natom])
     237        39596 :       pot_ace = SUM(energy(1:natom))
     238              : 
     239          206 :       DEALLOCATE (forceunroll)
     240              : 
     241              : #else
     242              :       pot_ace = 0.0
     243              :       ace_force = 0
     244              :       ace_virial = 0.0
     245              :       MARK_USED(ace_natom)
     246              :       MARK_USED(ace_atype)
     247              :       MARK_USED(fist_nonbond_env)
     248              :       MARK_USED(cell)
     249              :       MARK_USED(ace_data)
     250              :       CPABORT("CP2K was compiled without ACE library.")
     251              : #endif
     252              : 
     253          206 :    END SUBROUTINE ace_interface
     254              : 
     255              : !----------------------------------------------------------------------------------
     256              : 
     257              : END MODULE ace_nlist
        

Generated by: LCOV version 2.0-1