LCOV - code coverage report
Current view: top level - src - manybody_quip.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 59 67 88.1 %
Date: 2024-12-21 06:28:57 Functions: 2 2 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : MODULE manybody_quip
       9             : 
      10             :    USE cp_log_handling, ONLY: cp_logger_get_default_io_unit
      11             :    USE atomic_kind_types, ONLY: atomic_kind_type
      12             :    USE bibliography, ONLY: QUIP_ref, &
      13             :                            cite_reference
      14             :    USE cell_types, ONLY: cell_type
      15             :    USE message_passing, ONLY: mp_para_env_type
      16             :    USE fist_nonbond_env_types, ONLY: fist_nonbond_env_get, &
      17             :                                      fist_nonbond_env_set, &
      18             :                                      fist_nonbond_env_type, &
      19             :                                      quip_data_type
      20             :    USE kinds, ONLY: dp
      21             :    USE pair_potential_types, ONLY: pair_potential_pp_type, &
      22             :                                    pair_potential_single_type, &
      23             :                                    quip_pot_type, &
      24             :                                    quip_type
      25             :    USE particle_types, ONLY: particle_type
      26             :    USE physcon, ONLY: angstrom, &
      27             :                       evolt
      28             : #ifdef __QUIP
      29             :    USE quip_unified_wrapper_module, ONLY: quip_unified_wrapper
      30             : #endif
      31             : 
      32             : #include "./base/base_uses.f90"
      33             : 
      34             :    IMPLICIT NONE
      35             : 
      36             :    PRIVATE
      37             : 
      38             :    PUBLIC quip_energy_store_force_virial, quip_add_force_virial
      39             : 
      40             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'manybody_quip'
      41             : 
      42             : CONTAINS
      43             : 
      44             : ! **************************************************************************************************
      45             : !> \brief ...
      46             : !> \param particle_set ...
      47             : !> \param cell ...
      48             : !> \param atomic_kind_set ...
      49             : !> \param potparm ...
      50             : !> \param fist_nonbond_env ...
      51             : !> \param pot_quip ...
      52             : !> \param para_env ...
      53             : ! **************************************************************************************************
      54           2 :    SUBROUTINE quip_energy_store_force_virial(particle_set, cell, atomic_kind_set, potparm, fist_nonbond_env, &
      55             :                                              pot_quip, para_env)
      56             :       TYPE(particle_type), POINTER             :: particle_set(:)
      57             :       TYPE(cell_type), POINTER                 :: cell
      58             :       TYPE(atomic_kind_type), POINTER          :: atomic_kind_set(:)
      59             :       TYPE(pair_potential_pp_type), POINTER    :: potparm
      60             :       TYPE(fist_nonbond_env_type), POINTER     :: fist_nonbond_env
      61             :       REAL(kind=dp)                            :: pot_quip
      62             :       TYPE(mp_para_env_type), OPTIONAL, &
      63             :          POINTER                                :: para_env
      64             : 
      65             : #ifdef __QUIP
      66           2 :       CHARACTER(len=2), ALLOCATABLE            :: elem_symbol(:)
      67             :       INTEGER                                  :: i, iat, iat_use, ikind, &
      68             :                                                   jkind, n_atoms, n_atoms_use, &
      69             :                                                   output_unit
      70             :       LOGICAL                                  :: do_parallel
      71           2 :       LOGICAL, ALLOCATABLE                     :: use_atom(:)
      72             :       REAL(kind=dp)                            :: lattice(3, 3), virial(3, 3)
      73           2 :       REAL(kind=dp), ALLOCATABLE               :: force(:, :), pos(:, :)
      74             :       TYPE(pair_potential_single_type), &
      75             :          POINTER                                :: pot
      76             :       TYPE(quip_data_type), POINTER            :: quip_data
      77             :       TYPE(quip_pot_type), POINTER             :: quip
      78             : 
      79             : #endif
      80             : #ifndef __QUIP
      81             :       MARK_USED(particle_set)
      82             :       MARK_USED(cell)
      83             :       MARK_USED(atomic_kind_set)
      84             :       MARK_USED(potparm)
      85             :       MARK_USED(fist_nonbond_env)
      86             :       MARK_USED(pot_quip)
      87             :       MARK_USED(para_env)
      88             :       CALL cp_abort(__LOCATION__, "In order to use QUIP you need to download "// &
      89             :                     "and install the libAtoms/QUIP library (check CP2K manual for details)")
      90             : #else
      91           2 :       n_atoms = SIZE(particle_set)
      92           6 :       ALLOCATE (use_atom(n_atoms))
      93           8 :       use_atom = .FALSE.
      94             : 
      95           2 :       NULLIFY (quip)
      96             : 
      97           4 :       DO ikind = 1, SIZE(atomic_kind_set)
      98           6 :       DO jkind = 1, SIZE(atomic_kind_set)
      99           2 :          pot => potparm%pot(ikind, jkind)%pot
     100           6 :          DO i = 1, SIZE(pot%type)
     101           2 :             IF (pot%type(i) /= quip_type) CYCLE
     102           2 :             IF (.NOT. ASSOCIATED(quip)) quip => pot%set(i)%quip
     103          10 :             DO iat = 1, n_atoms
     104           6 :                IF (particle_set(iat)%atomic_kind%kind_number == ikind .OR. &
     105           8 :                    particle_set(iat)%atomic_kind%kind_number == jkind) use_atom(iat) = .TRUE.
     106             :             END DO ! iat
     107             :          END DO ! i
     108             :       END DO ! jkind
     109             :       END DO ! ikind
     110           8 :       n_atoms_use = COUNT(use_atom)
     111          10 :       ALLOCATE (pos(3, n_atoms_use), force(3, n_atoms_use), elem_symbol(n_atoms_use))
     112             : 
     113           8 :       iat_use = 0
     114           8 :       DO iat = 1, n_atoms
     115           6 :          IF (.NOT. use_atom(iat)) CYCLE
     116           6 :          iat_use = iat_use + 1
     117          24 :          pos(1:3, iat_use) = particle_set(iat)%r*angstrom
     118           8 :          elem_symbol(iat_use) = particle_set(iat)%atomic_kind%element_symbol
     119             :       END DO
     120           2 :       IF (iat_use > 0) CALL cite_reference(QUIP_ref)
     121           2 :       output_unit = cp_logger_get_default_io_unit()
     122          26 :       lattice = cell%hmat*angstrom
     123           2 :       do_parallel = .FALSE.
     124           2 :       IF (PRESENT(para_env)) THEN
     125           2 :          do_parallel = para_env%num_pe > 1
     126             :       END IF
     127           2 :       IF (do_parallel) THEN
     128             :          CALL quip_unified_wrapper( &
     129             :             N=n_atoms_use, pos=pos, lattice=lattice, symbol=elem_symbol, &
     130             :             quip_param_file=TRIM(quip%quip_file_name), &
     131             :             quip_param_file_len=LEN_TRIM(quip%quip_file_name), &
     132             :             init_args_str=TRIM(quip%init_args), &
     133             :             init_args_str_len=LEN_TRIM(quip%init_args), &
     134             :             calc_args_str=TRIM(quip%calc_args), &
     135             :             calc_args_str_len=LEN_TRIM(quip%calc_args), &
     136             :             energy=pot_quip, force=force, virial=virial, &
     137           2 :             output_unit=output_unit, mpi_communicator=para_env%get_handle())
     138             :       ELSE
     139             :          CALL quip_unified_wrapper( &
     140             :             N=n_atoms_use, pos=pos, lattice=lattice, symbol=elem_symbol, &
     141             :             quip_param_file=TRIM(quip%quip_file_name), &
     142             :             quip_param_file_len=LEN_TRIM(quip%quip_file_name), &
     143             :             init_args_str=TRIM(quip%init_args), &
     144             :             init_args_str_len=LEN_TRIM(quip%init_args), &
     145             :             calc_args_str=TRIM(quip%calc_args), &
     146             :             calc_args_str_len=LEN_TRIM(quip%calc_args), &
     147           0 :             energy=pot_quip, force=force, virial=virial, output_unit=output_unit)
     148             :       END IF
     149             :       ! convert units
     150           2 :       pot_quip = pot_quip/evolt
     151          26 :       force = force/(evolt/angstrom)
     152          26 :       virial = virial/evolt
     153             :       ! account for double counting from multiple MPI processes
     154           2 :       IF (PRESENT(para_env)) pot_quip = pot_quip/REAL(para_env%num_pe, dp)
     155          26 :       IF (PRESENT(para_env)) force = force/REAL(para_env%num_pe, dp)
     156          26 :       IF (PRESENT(para_env)) virial = virial/REAL(para_env%num_pe, dp)
     157             :       ! get quip_data to save force, virial info
     158           2 :       CALL fist_nonbond_env_get(fist_nonbond_env, quip_data=quip_data)
     159           2 :       IF (.NOT. ASSOCIATED(quip_data)) THEN
     160          26 :          ALLOCATE (quip_data)
     161           2 :          CALL fist_nonbond_env_set(fist_nonbond_env, quip_data=quip_data)
     162           2 :          NULLIFY (quip_data%use_indices, quip_data%force)
     163             :       END IF
     164           2 :       IF (ASSOCIATED(quip_data%force)) THEN
     165           0 :          IF (SIZE(quip_data%force, 2) /= n_atoms_use) THEN
     166           0 :             DEALLOCATE (quip_data%force, quip_data%use_indices)
     167             :          END IF
     168             :       END IF
     169           2 :       IF (.NOT. ASSOCIATED(quip_data%force)) THEN
     170           4 :          ALLOCATE (quip_data%force(3, n_atoms_use))
     171           6 :          ALLOCATE (quip_data%use_indices(n_atoms_use))
     172             :       END IF
     173             :       ! save force, virial info
     174             :       iat_use = 0
     175           8 :       DO iat = 1, n_atoms
     176           8 :          IF (use_atom(iat)) THEN
     177           6 :             iat_use = iat_use + 1
     178           6 :             quip_data%use_indices(iat_use) = iat
     179             :          END IF
     180             :       END DO
     181          26 :       quip_data%force = force
     182          26 :       quip_data%virial = virial
     183             : 
     184           2 :       DEALLOCATE (use_atom, pos, force, elem_symbol)
     185             : #endif
     186           2 :    END SUBROUTINE quip_energy_store_force_virial
     187             : 
     188             : ! **************************************************************************************************
     189             : !> \brief ...
     190             : !> \param fist_nonbond_env ...
     191             : !> \param force ...
     192             : !> \param virial ...
     193             : ! **************************************************************************************************
     194        9330 :    SUBROUTINE quip_add_force_virial(fist_nonbond_env, force, virial)
     195             :       TYPE(fist_nonbond_env_type), POINTER     :: fist_nonbond_env
     196             :       REAL(KIND=dp)                            :: force(:, :), virial(3, 3)
     197             : 
     198             : #ifdef __QUIP
     199             :       INTEGER                                  :: iat, iat_use
     200             :       TYPE(quip_data_type), POINTER            :: quip_data
     201             : #endif
     202             : 
     203             : #ifndef __QUIP
     204             :       MARK_USED(fist_nonbond_env)
     205             :       MARK_USED(force)
     206             :       MARK_USED(virial)
     207             :       RETURN
     208             : #else
     209        9330 :       CALL fist_nonbond_env_get(fist_nonbond_env, quip_data=quip_data)
     210        9330 :       IF (.NOT. ASSOCIATED(quip_data)) RETURN
     211             : 
     212           0 :       DO iat_use = 1, SIZE(quip_data%use_indices)
     213           0 :          iat = quip_data%use_indices(iat_use)
     214           0 :          CPASSERT(iat >= 1 .AND. iat <= SIZE(force, 2))
     215           0 :          force(1:3, iat) = force(1:3, iat) + quip_data%force(1:3, iat_use)
     216             :       END DO
     217           0 :       virial = virial + quip_data%virial
     218             : #endif
     219             :    END SUBROUTINE quip_add_force_virial
     220             : 
     221             : END MODULE manybody_quip

Generated by: LCOV version 1.15