LCOV - code coverage report
Current view: top level - src - ace_nlist.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:dc5a454) Lines: 102 102 100.0 %
Date: 2025-06-17 07:40:17 Functions: 1 1 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 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             :       MARK_USED(ace_natom)
     243             :       MARK_USED(ace_atype)
     244             :       MARK_USED(pot_ace)
     245             :       MARK_USED(ace_force)
     246             :       MARK_USED(ace_virial)
     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 1.15