LCOV - code coverage report
Current view: top level - src - manybody_deepmd.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:42dac4a) Lines: 94.0 % 83 78
Test Date: 2025-07-25 12:55:17 Functions: 100.0 % 2 2

            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              : MODULE manybody_deepmd
       9              : 
      10              :    USE atomic_kind_types,               ONLY: atomic_kind_type
      11              :    USE bibliography,                    ONLY: Wang2018,&
      12              :                                               Zeng2023,&
      13              :                                               cite_reference
      14              :    USE cell_types,                      ONLY: cell_type
      15              :    USE cp_log_handling,                 ONLY: cp_logger_get_default_io_unit
      16              :    USE deepmd_wrapper,                  ONLY: deepmd_model_compute,&
      17              :                                               deepmd_model_load
      18              :    USE fist_nonbond_env_types,          ONLY: deepmd_data_type,&
      19              :                                               fist_nonbond_env_get,&
      20              :                                               fist_nonbond_env_set,&
      21              :                                               fist_nonbond_env_type
      22              :    USE kinds,                           ONLY: dp
      23              :    USE message_passing,                 ONLY: mp_para_env_type
      24              :    USE pair_potential_types,            ONLY: deepmd_type,&
      25              :                                               pair_potential_pp_type,&
      26              :                                               pair_potential_single_type
      27              :    USE particle_types,                  ONLY: particle_type
      28              :    USE physcon,                         ONLY: angstrom,&
      29              :                                               evolt
      30              : #include "./base/base_uses.f90"
      31              : 
      32              :    IMPLICIT NONE
      33              : 
      34              :    PRIVATE
      35              :    PUBLIC deepmd_energy_store_force_virial, deepmd_add_force_virial
      36              : 
      37              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'manybody_deepmd'
      38              : 
      39              : CONTAINS
      40              : 
      41              : ! **************************************************************************************************
      42              : !> \brief ...
      43              : !> \param particle_set ...
      44              : !> \param cell ...
      45              : !> \param atomic_kind_set ...
      46              : !> \param potparm ...
      47              : !> \param fist_nonbond_env ...
      48              : !> \param pot_deepmd ...
      49              : !> \param para_env ...
      50              : ! **************************************************************************************************
      51            2 :    SUBROUTINE deepmd_energy_store_force_virial(particle_set, cell, atomic_kind_set, potparm, fist_nonbond_env, &
      52              :                                                pot_deepmd, para_env)
      53              :       TYPE(particle_type), POINTER                       :: particle_set(:)
      54              :       TYPE(cell_type), POINTER                           :: cell
      55              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind_set(:)
      56              :       TYPE(pair_potential_pp_type), POINTER              :: potparm
      57              :       TYPE(fist_nonbond_env_type), POINTER               :: fist_nonbond_env
      58              :       REAL(kind=dp)                                      :: pot_deepmd
      59              :       TYPE(mp_para_env_type), OPTIONAL, POINTER          :: para_env
      60              : 
      61              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'deepmd_energy_store_force_virial'
      62              : 
      63              :       INTEGER                                            :: dpmd_natoms, handle, i, iat, iat_use, &
      64              :                                                             ikind, jkind, n_atoms, n_atoms_use, &
      65              :                                                             output_unit
      66            2 :       INTEGER, ALLOCATABLE                               :: dpmd_atype(:), use_atom_type(:)
      67            2 :       LOGICAL, ALLOCATABLE                               :: use_atom(:)
      68              :       REAL(kind=dp)                                      :: lattice(3, 3)
      69            2 :       REAL(kind=dp), ALLOCATABLE                         :: dpmd_atomic_energy(:), &
      70            2 :                                                             dpmd_atomic_virial(:), dpmd_cell(:), &
      71            2 :                                                             dpmd_coord(:), dpmd_force(:), &
      72            2 :                                                             dpmd_virial(:)
      73              :       TYPE(deepmd_data_type), POINTER                    :: deepmd_data
      74              :       TYPE(pair_potential_single_type), POINTER          :: pot
      75              : 
      76            2 :       CALL timeset(routineN, handle)
      77            2 :       n_atoms = SIZE(particle_set)
      78            6 :       ALLOCATE (use_atom(n_atoms))
      79            4 :       ALLOCATE (use_atom_type(n_atoms))
      80            8 :       use_atom = .FALSE.
      81            8 :       use_atom_type = 0
      82              : 
      83            6 :       DO ikind = 1, SIZE(atomic_kind_set)
      84           14 :          DO jkind = 1, SIZE(atomic_kind_set)
      85            8 :             pot => potparm%pot(ikind, jkind)%pot
      86              :             ! ensure that each atom is only used once
      87            8 :             IF (ikind /= jkind) CYCLE
      88           12 :             DO i = 1, SIZE(pot%type)
      89            4 :                IF (pot%type(i) /= deepmd_type) CYCLE
      90           24 :                DO iat = 1, n_atoms
      91           12 :                   IF (particle_set(iat)%atomic_kind%kind_number == ikind .OR. &
      92            4 :                       particle_set(iat)%atomic_kind%kind_number == jkind) THEN
      93            6 :                      use_atom(iat) = .TRUE.
      94            6 :                      use_atom_type(iat) = pot%set(i)%deepmd%atom_deepmd_type
      95              :                   END IF
      96              :                END DO ! iat
      97              :             END DO ! i
      98              :          END DO ! jkind
      99              :       END DO ! ikind
     100              : 
     101            8 :       n_atoms_use = COUNT(use_atom)
     102            2 :       dpmd_natoms = n_atoms_use
     103              :       ALLOCATE (dpmd_cell(9), dpmd_atype(dpmd_natoms), dpmd_coord(dpmd_natoms*3), &
     104              :                 dpmd_force(dpmd_natoms*3), dpmd_virial(9), &
     105           20 :                 dpmd_atomic_energy(dpmd_natoms), dpmd_atomic_virial(dpmd_natoms*9))
     106              : 
     107            8 :       iat_use = 0
     108            8 :       DO iat = 1, n_atoms
     109            6 :          IF (.NOT. use_atom(iat)) CYCLE
     110            6 :          iat_use = iat_use + 1
     111           24 :          dpmd_coord((iat_use - 1)*3 + 1:(iat_use - 1)*3 + 3) = particle_set(iat)%r*angstrom
     112            8 :          dpmd_atype(iat_use) = use_atom_type(iat)
     113              :       END DO
     114            2 :       IF (iat_use > 0) THEN
     115            2 :          CALL cite_reference(Wang2018)
     116            2 :          CALL cite_reference(Zeng2023)
     117              :       END IF
     118            2 :       output_unit = cp_logger_get_default_io_unit()
     119           26 :       lattice = cell%hmat*angstrom
     120              : 
     121              :       ! change matrix to one d array
     122            8 :       DO i = 1, 3
     123           26 :          dpmd_cell((i - 1)*3 + 1:(i - 1)*3 + 3) = lattice(:, i)
     124              :       END DO
     125              : 
     126              :       ! get deepmd_data to save force, virial info
     127            2 :       CALL fist_nonbond_env_get(fist_nonbond_env, deepmd_data=deepmd_data)
     128            2 :       IF (.NOT. ASSOCIATED(deepmd_data)) THEN
     129           28 :          ALLOCATE (deepmd_data)
     130            2 :          CALL fist_nonbond_env_set(fist_nonbond_env, deepmd_data=deepmd_data)
     131            2 :          NULLIFY (deepmd_data%use_indices, deepmd_data%force)
     132            2 :          deepmd_data%model = deepmd_model_load(filename=pot%set(1)%deepmd%deepmd_file_name)
     133              :       END IF
     134            2 :       IF (ASSOCIATED(deepmd_data%force)) THEN
     135            0 :          IF (SIZE(deepmd_data%force, 2) /= n_atoms_use) THEN
     136            0 :             DEALLOCATE (deepmd_data%force, deepmd_data%use_indices)
     137              :          END IF
     138              :       END IF
     139            2 :       IF (.NOT. ASSOCIATED(deepmd_data%force)) THEN
     140            6 :          ALLOCATE (deepmd_data%force(3, n_atoms_use))
     141            4 :          ALLOCATE (deepmd_data%use_indices(n_atoms_use))
     142              :       END IF
     143              : 
     144              :       CALL deepmd_model_compute(model=deepmd_data%model, &
     145              :                                 natom=dpmd_natoms, &
     146              :                                 coord=dpmd_coord, &
     147              :                                 atype=dpmd_atype, &
     148              :                                 cell=dpmd_cell, &
     149              :                                 energy=pot_deepmd, &
     150              :                                 force=dpmd_force, &
     151              :                                 virial=dpmd_virial, &
     152              :                                 atomic_energy=dpmd_atomic_energy, &
     153            2 :                                 atomic_virial=dpmd_atomic_virial)
     154              : 
     155              :       ! convert units
     156            2 :       pot_deepmd = pot_deepmd/evolt
     157           20 :       dpmd_force = dpmd_force/(evolt/angstrom)
     158           20 :       dpmd_virial = dpmd_virial/evolt
     159              : 
     160              :       ! account for double counting from multiple MPI processes
     161            2 :       IF (PRESENT(para_env)) THEN
     162            2 :          pot_deepmd = pot_deepmd/REAL(para_env%num_pe, dp)
     163           20 :          dpmd_force = dpmd_force/REAL(para_env%num_pe, dp)
     164           20 :          dpmd_virial = dpmd_virial/REAL(para_env%num_pe, dp)
     165              :       END IF
     166              : 
     167              :       ! save force, virial info
     168              :       iat_use = 0
     169            8 :       DO iat = 1, n_atoms
     170            8 :          IF (use_atom(iat)) THEN
     171            6 :             iat_use = iat_use + 1
     172            6 :             deepmd_data%use_indices(iat_use) = iat
     173           24 :             deepmd_data%force(1:3, iat_use) = dpmd_force((iat_use - 1)*3 + 1:(iat_use - 1)*3 + 3)
     174              :          END IF
     175              :       END DO
     176            8 :       DO i = 1, 3
     177           26 :          deepmd_data%virial(1:3, i) = dpmd_virial((i - 1)*3 + 1:(i - 1)*3 + 3)
     178              :       END DO
     179            0 :       DEALLOCATE (use_atom, use_atom_type, dpmd_coord, dpmd_force, &
     180            0 :                   dpmd_virial, dpmd_atomic_energy, dpmd_atomic_virial, &
     181            2 :                   dpmd_cell, dpmd_atype)
     182              : 
     183            2 :       CALL timestop(handle)
     184            4 :    END SUBROUTINE deepmd_energy_store_force_virial
     185              : 
     186              : ! **************************************************************************************************
     187              : !> \brief ...
     188              : !> \param fist_nonbond_env ...
     189              : !> \param force ...
     190              : !> \param pv_nonbond ...
     191              : !> \param use_virial ...
     192              : ! **************************************************************************************************
     193            2 :    SUBROUTINE deepmd_add_force_virial(fist_nonbond_env, force, pv_nonbond, use_virial)
     194              :       TYPE(fist_nonbond_env_type), POINTER               :: fist_nonbond_env
     195              :       REAL(KIND=dp)                                      :: force(:, :), pv_nonbond(3, 3)
     196              :       LOGICAL, OPTIONAL                                  :: use_virial
     197              : 
     198              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'deepmd_add_force_virial'
     199              : 
     200              :       INTEGER                                            :: handle, iat, iat_use
     201              :       TYPE(deepmd_data_type), POINTER                    :: deepmd_data
     202              : 
     203            2 :       CALL timeset(routineN, handle)
     204              : 
     205            2 :       CALL fist_nonbond_env_get(fist_nonbond_env, deepmd_data=deepmd_data)
     206              : 
     207            2 :       IF (.NOT. ASSOCIATED(deepmd_data)) RETURN
     208              : 
     209            8 :       DO iat_use = 1, SIZE(deepmd_data%use_indices)
     210            6 :          iat = deepmd_data%use_indices(iat_use)
     211            6 :          CPASSERT(iat >= 1 .AND. iat <= SIZE(force, 2))
     212           26 :          force(1:3, iat) = force(1:3, iat) + deepmd_data%force(1:3, iat_use)
     213              :       END DO
     214              : 
     215            2 :       IF (use_virial) THEN
     216            0 :          pv_nonbond = pv_nonbond + deepmd_data%virial
     217              :       END IF
     218              : 
     219            2 :       CALL timestop(handle)
     220              :    END SUBROUTINE deepmd_add_force_virial
     221              : 
     222              : END MODULE manybody_deepmd
        

Generated by: LCOV version 2.0-1