LCOV - code coverage report
Current view: top level - src - manybody_gal21.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 266 332 80.1 %
Date: 2024-12-21 06:28:57 Functions: 9 10 90.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             : ! **************************************************************************************************
       9             : !> \brief Implementation of the GAL21 potential
      10             : !>
      11             : !> \author Clabaut Paul
      12             : ! **************************************************************************************************
      13             : MODULE manybody_gal21
      14             : 
      15             :    USE atomic_kind_types,               ONLY: get_atomic_kind
      16             :    USE cell_types,                      ONLY: cell_type,&
      17             :                                               pbc
      18             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      19             :                                               cp_logger_type,&
      20             :                                               cp_to_string
      21             :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      22             :                                               cp_print_key_unit_nr
      23             :    USE fist_neighbor_list_types,        ONLY: fist_neighbor_type,&
      24             :                                               neighbor_kind_pairs_type
      25             :    USE fist_nonbond_env_types,          ONLY: pos_type
      26             :    USE input_section_types,             ONLY: section_vals_type
      27             :    USE kinds,                           ONLY: dp
      28             :    USE message_passing,                 ONLY: mp_para_env_type
      29             :    USE pair_potential_types,            ONLY: gal21_pot_type,&
      30             :                                               gal21_type,&
      31             :                                               pair_potential_pp_type,&
      32             :                                               pair_potential_single_type
      33             :    USE particle_types,                  ONLY: particle_type
      34             :    USE util,                            ONLY: sort
      35             : #include "./base/base_uses.f90"
      36             : 
      37             :    IMPLICIT NONE
      38             : 
      39             :    PRIVATE
      40             :    PUBLIC :: setup_gal21_arrays, destroy_gal21_arrays, &
      41             :              gal21_energy, gal21_forces, &
      42             :              print_nr_ions_gal21
      43             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'manybody_gal21'
      44             : 
      45             : CONTAINS
      46             : 
      47             : ! **************************************************************************************************
      48             : !> \brief  Main part of the energy evaluation of GAL2119
      49             : !> \param pot_loc value of total potential energy
      50             : !> \param gal21 all parameters of GAL2119
      51             : !> \param r_last_update_pbc position of every atoms on previous frame
      52             : !> \param iparticle first index of the atom of the evaluated pair
      53             : !> \param jparticle second index of the atom of the evaluated pair
      54             : !> \param cell dimension of the pbc cell
      55             : !> \param particle_set full list of atoms of the system
      56             : !> \param mm_section ...
      57             : !> \author Clabaut Paul - 2019 - ENS de Lyon
      58             : ! **************************************************************************************************
      59        5732 :    SUBROUTINE gal21_energy(pot_loc, gal21, r_last_update_pbc, iparticle, jparticle, &
      60             :                            cell, particle_set, mm_section)
      61             : 
      62             :       REAL(KIND=dp), INTENT(OUT)                         :: pot_loc
      63             :       TYPE(gal21_pot_type), POINTER                      :: gal21
      64             :       TYPE(pos_type), DIMENSION(:), POINTER              :: r_last_update_pbc
      65             :       INTEGER, INTENT(IN)                                :: iparticle, jparticle
      66             :       TYPE(cell_type), POINTER                           :: cell
      67             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
      68             :       TYPE(section_vals_type), POINTER                   :: mm_section
      69             : 
      70             :       CHARACTER(LEN=2)                                   :: element_symbol
      71             :       INTEGER                                            :: index_outfile
      72             :       REAL(KIND=dp)                                      :: anglepart, AO, BO, bxy, bz, cosalpha, &
      73             :                                                             drji2, eps, nvec(3), rji(3), sinalpha, &
      74             :                                                             sum_weight, Vang, Vgaussian, VH, VTT, &
      75             :                                                             weight
      76             :       TYPE(cp_logger_type), POINTER                      :: logger
      77             : 
      78        5732 :       pot_loc = 0.0_dp
      79             :       CALL get_atomic_kind(atomic_kind=particle_set(iparticle)%atomic_kind, &
      80        5732 :                            element_symbol=element_symbol) !Read the atom type of i
      81             : 
      82        5732 :       IF (element_symbol == "O") THEN !To avoid counting two times each pair
      83             : 
      84        2866 :          rji(:) = pbc(r_last_update_pbc(jparticle)%r(:), r_last_update_pbc(iparticle)%r(:), cell) !Vector in pbc from j to i
      85             : 
      86        2866 :          IF (.NOT. ALLOCATED(gal21%n_vectors)) THEN !First calling of the forcefield only
      87           3 :             ALLOCATE (gal21%n_vectors(3, SIZE(particle_set)))
      88        3481 :             gal21%n_vectors(:, :) = 0.0_dp
      89             :          END IF
      90             : 
      91        2866 :          IF (gal21%express) THEN
      92           0 :             logger => cp_get_default_logger()
      93             :             index_outfile = cp_print_key_unit_nr(logger, mm_section, &
      94           0 :                                                  "PRINT%PROGRAM_RUN_INFO", extension=".mmLog")
      95           0 :             IF (index_outfile > 0) WRITE (index_outfile, *) "GCN", gal21%gcn(jparticle)
      96             :             CALL cp_print_key_finished_output(index_outfile, logger, mm_section, &
      97           0 :                                               "PRINT%PROGRAM_RUN_INFO")
      98             :          END IF
      99             : 
     100             :          !Build epsilon attraction and the parameters of the gaussian attraction as a function of gcn
     101        2866 :          eps = gal21%epsilon1*gal21%gcn(jparticle)*gal21%gcn(jparticle) + gal21%epsilon2*gal21%gcn(jparticle) + gal21%epsilon3
     102        2866 :          bxy = gal21%bxy1 + gal21%bxy2*gal21%gcn(jparticle)
     103        2866 :          bz = gal21%bz1 + gal21%bz2*gal21%gcn(jparticle)
     104             : 
     105             :          !Angular dependance %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     106        2866 :          Vang = 0.0_dp
     107             : 
     108             :          !Calculation of the normal vector centered on the Me atom of the pair, only the first time that an interaction with the metal atom of the pair is evaluated
     109             :          IF (gal21%n_vectors(1, jparticle) == 0.0_dp .AND. &
     110        2866 :              gal21%n_vectors(2, jparticle) == 0.0_dp .AND. &
     111             :              gal21%n_vectors(3, jparticle) == 0.0_dp) THEN
     112             :             gal21%n_vectors(:, jparticle) = normale(gal21, r_last_update_pbc, jparticle, &
     113         596 :                                                     particle_set, cell)
     114             :          END IF
     115             : 
     116       11464 :          nvec(:) = gal21%n_vectors(:, jparticle) !Else, retrive it, should not have moved sinc metal is supposed to be frozen
     117             : 
     118             :          !Calculation of the sum of the expontial weights of each Me surrounding the principal one
     119        2866 :          sum_weight = somme(gal21, r_last_update_pbc, iparticle, particle_set, cell)
     120             : 
     121             :          !Exponential damping weight for angular dependance
     122       11464 :          weight = EXP(-SQRT(DOT_PRODUCT(rji, rji))/gal21%r1)
     123             : 
     124             :          !Calculation of the truncated fourier series of the water-dipole/surface-normal angle
     125             :          anglepart = 0.0_dp
     126             :          VH = 0.0_dp
     127             :          CALL angular(anglepart, VH, gal21, r_last_update_pbc, iparticle, jparticle, cell, particle_set, nvec, &
     128        2866 :                       .TRUE., mm_section)
     129             : 
     130             :          !Build the complete angular potential while avoiding division by 0
     131        2866 :          IF (weight /= 0) THEN
     132        2866 :             Vang = weight*weight*anglepart/sum_weight
     133        2866 :             IF (gal21%express) THEN
     134           0 :                logger => cp_get_default_logger()
     135             :                index_outfile = cp_print_key_unit_nr(logger, mm_section, &
     136           0 :                                                     "PRINT%PROGRAM_RUN_INFO", extension=".mmLog")
     137           0 :                IF (index_outfile > 0) WRITE (index_outfile, *) "Fermi", weight*weight/sum_weight
     138             :                CALL cp_print_key_finished_output(index_outfile, logger, mm_section, &
     139           0 :                                                  "PRINT%PROGRAM_RUN_INFO")
     140             :             END IF
     141             :          END IF
     142             :          !END Angular%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     143             : 
     144             :          !Attractive Gaussian %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     145        2866 :          Vgaussian = 0.0_dp
     146       11464 :          drji2 = DOT_PRODUCT(rji, rji)
     147             :          !Alpha is the angle of the Me-O vector with the normale vector. Used for gaussian attaction
     148             : 
     149       11464 :          cosalpha = DOT_PRODUCT(rji, nvec)/SQRT(drji2)
     150        2866 :          IF (cosalpha < -1.0_dp) cosalpha = -1.0_dp
     151        2866 :          IF (cosalpha > +1.0_dp) cosalpha = +1.0_dp
     152        2866 :          sinalpha = SIN(ACOS(cosalpha))
     153             : 
     154             :          !Gaussian component of the energy
     155             :          Vgaussian = -1.0_dp*eps*EXP(-bz*drji2*cosalpha*cosalpha &
     156        2866 :                                      - bxy*drji2*sinalpha*sinalpha)
     157             :          !END Gaussian%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     158             : 
     159        2866 :          AO = gal21%AO1 + gal21%AO2*gal21%gcn(jparticle)
     160        2866 :          BO = gal21%BO1 + gal21%BO2*gal21%gcn(jparticle)
     161             : 
     162             :          !Tang and toennies potential for physisorption
     163             :          VTT = AO*EXP(-BO*SQRT(drji2)) - (1.0 - EXP(-BO*SQRT(drji2)) &
     164             :                                           - BO*SQRT(drji2)*EXP(-BO*SQRT(drji2)) &
     165             :                                           - (((BO*SQRT(drji2))**2)/2)*EXP(-BO*SQRT(drji2)) &
     166             :                                           - (((BO*SQRT(drji2))**3)/6)*EXP(-BO*SQRT(drji2)) &
     167             :                                           - (((BO*SQRT(drji2))**4)/24)*EXP(-BO*SQRT(drji2)) &
     168             :                                           - (((BO*SQRT(drji2))**5)/120)*EXP(-BO*SQRT(drji2)) &
     169             :                                           - (((BO*SQRT(drji2))**6)/720)*EXP(-BO*SQRT(drji2))) &
     170        2866 :                *gal21%c/(SQRT(drji2)**6)
     171             : 
     172             :          !For fit purpose only
     173        2866 :          IF (gal21%express) THEN
     174           0 :             logger => cp_get_default_logger()
     175             :             index_outfile = cp_print_key_unit_nr(logger, mm_section, &
     176           0 :                                                  "PRINT%PROGRAM_RUN_INFO", extension=".mmLog")
     177           0 :             IF (index_outfile > 0) WRITE (index_outfile, *) "Gau", -1.0_dp*EXP(-bz*drji2*cosalpha*cosalpha &
     178           0 :                                                                                - bxy*drji2*sinalpha*sinalpha)
     179           0 :             IF (weight == 0 .AND. index_outfile > 0) WRITE (index_outfile, *) "Fermi  0"
     180           0 :             IF (index_outfile > 0) WRITE (index_outfile, *) "expO", EXP(-BO*SQRT(drji2))
     181           0 :             IF (index_outfile > 0) WRITE (index_outfile, *) "cstpart", -(1.0 - EXP(-BO*SQRT(drji2)) &
     182             :                                                                          - BO*SQRT(drji2)*EXP(-BO*SQRT(drji2)) &
     183             :                                                                          - (((BO*SQRT(drji2))**2)/2)*EXP(-BO*SQRT(drji2)) &
     184             :                                                                          - (((BO*SQRT(drji2))**3)/6)*EXP(-BO*SQRT(drji2)) &
     185             :                                                                          - (((BO*SQRT(drji2))**4)/24)*EXP(-BO*SQRT(drji2)) &
     186             :                                                                          - (((BO*SQRT(drji2))**5)/120)*EXP(-BO*SQRT(drji2)) &
     187             :                                                                          - (((BO*SQRT(drji2))**6)/720)*EXP(-BO*SQRT(drji2))) &
     188           0 :                *gal21%c/(SQRT(drji2)**6)
     189           0 :             IF (index_outfile > 0) WRITE (index_outfile, *) "params_lin_eps", gal21%epsilon1, gal21%epsilon2, gal21%epsilon3
     190           0 :             IF (index_outfile > 0) WRITE (index_outfile, *) "params_lin_A0", AO
     191             :             CALL cp_print_key_finished_output(index_outfile, logger, mm_section, &
     192           0 :                                               "PRINT%PROGRAM_RUN_INFO")
     193             :          END IF
     194             :          !Compute the total energy
     195        2866 :          pot_loc = Vgaussian + Vang + VTT + VH
     196             : 
     197             :       END IF
     198             : 
     199        5732 :    END SUBROUTINE gal21_energy
     200             : 
     201             : ! **************************************************************************************************
     202             : !> \brief The idea is to build a vector normal to the local surface by using the symetry of the
     203             : !>        surface that make the opposite vectors compensate themself. The vector is therefore in the
     204             : !>.       direction of the missing atoms of a large coordination sphere
     205             : !> \param gal21 ...
     206             : !> \param r_last_update_pbc ...
     207             : !> \param jparticle ...
     208             : !> \param particle_set ...
     209             : !> \param cell ...
     210             : !> \return ...
     211             : !> \retval normale ...
     212             : ! **************************************************************************************************
     213         149 :    FUNCTION normale(gal21, r_last_update_pbc, jparticle, particle_set, cell)
     214             :       TYPE(gal21_pot_type), POINTER                      :: gal21
     215             :       TYPE(pos_type), DIMENSION(:), POINTER              :: r_last_update_pbc
     216             :       INTEGER, INTENT(IN)                                :: jparticle
     217             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     218             :       TYPE(cell_type), POINTER                           :: cell
     219             :       REAL(KIND=dp)                                      :: normale(3)
     220             : 
     221             :       CHARACTER(LEN=2)                                   :: element_symbol_k
     222             :       INTEGER                                            :: kparticle, natom
     223             :       REAL(KIND=dp)                                      :: drjk, rjk(3)
     224             : 
     225         149 :       natom = SIZE(particle_set)
     226         596 :       normale(:) = 0.0_dp
     227             : 
     228      129779 :       DO kparticle = 1, natom !Loop on every atom of the system
     229      129630 :          IF (kparticle == jparticle) CYCLE !Avoid the principal Me atom (j) in the counting
     230             :          CALL get_atomic_kind(atomic_kind=particle_set(kparticle)%atomic_kind, &
     231      129481 :                               element_symbol=element_symbol_k)
     232      129481 :          IF (element_symbol_k /= gal21%met1 .AND. element_symbol_k /= gal21%met2) CYCLE !Keep only metals
     233       28459 :          rjk(:) = pbc(r_last_update_pbc(jparticle)%r(:), r_last_update_pbc(kparticle)%r(:), cell)
     234      113836 :          drjk = SQRT(DOT_PRODUCT(rjk, rjk))
     235       28459 :          IF (drjk > gal21%rcutsq) CYCLE !Keep only those within square root of the force-field cutoff distance of the metallic atom of the evaluated pair
     236      215156 :          normale(:) = normale(:) - rjk(:)/(drjk*drjk*drjk*drjk*drjk) !Build the normal, vector by vector
     237             :       END DO
     238             : 
     239             :       ! Normalisation of the vector
     240        1043 :       normale(:) = normale(:)/SQRT(DOT_PRODUCT(normale, normale))
     241             : 
     242             :    END FUNCTION normale
     243             : 
     244             : ! **************************************************************************************************
     245             : !> \brief Scan all the Me atoms that have been counted in the O-Me paires and sum their exp. weights
     246             : !> \param gal21 ...
     247             : !> \param r_last_update_pbc ...
     248             : !> \param iparticle ...
     249             : !> \param particle_set ...
     250             : !> \param cell ...
     251             : !> \return ...
     252             : !> \retval somme ...
     253             : ! **************************************************************************************************
     254        5732 :    FUNCTION somme(gal21, r_last_update_pbc, iparticle, particle_set, cell)
     255             :       TYPE(gal21_pot_type), POINTER                      :: gal21
     256             :       TYPE(pos_type), DIMENSION(:), POINTER              :: r_last_update_pbc
     257             :       INTEGER, INTENT(IN)                                :: iparticle
     258             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     259             :       TYPE(cell_type), POINTER                           :: cell
     260             :       REAL(KIND=dp)                                      :: somme
     261             : 
     262             :       CHARACTER(LEN=2)                                   :: element_symbol_k
     263             :       INTEGER                                            :: kparticle, natom
     264             :       REAL(KIND=dp)                                      :: rki(3)
     265             : 
     266        5732 :       natom = SIZE(particle_set)
     267        5732 :       somme = 0.0_dp
     268             : 
     269     4992572 :       DO kparticle = 1, natom !Loop on every atom of the system
     270             :          CALL get_atomic_kind(atomic_kind=particle_set(kparticle)%atomic_kind, &
     271     4986840 :                               element_symbol=element_symbol_k)
     272     4986840 :          IF (element_symbol_k /= gal21%met1 .AND. element_symbol_k /= gal21%met2) CYCLE !Keep only metals
     273     1100544 :          rki(:) = pbc(r_last_update_pbc(kparticle)%r(:), r_last_update_pbc(iparticle)%r(:), cell)
     274     4402176 :          IF (SQRT(DOT_PRODUCT(rki, rki)) > gal21%rcutsq) CYCLE !Keep only those within cutoff distance of the oxygen atom of the evaluated pair (the omega ensemble)
     275     4402176 :          IF (element_symbol_k == gal21%met1) somme = somme + EXP(-SQRT(DOT_PRODUCT(rki, rki))/gal21%r1) !Build the sum of the exponential weights
     276     1106276 :          IF (element_symbol_k == gal21%met2) somme = somme + EXP(-SQRT(DOT_PRODUCT(rki, rki))/gal21%r2) !Build the sum of the exponential weights
     277             :       END DO
     278             : 
     279        5732 :    END FUNCTION somme
     280             : 
     281             : ! **************************************************************************************************
     282             : !> \brief Compute the angular dependance (on theta) of the forcefield
     283             : !> \param anglepart ...
     284             : !> \param VH ...
     285             : !> \param gal21 ...
     286             : !> \param r_last_update_pbc ...
     287             : !> \param iparticle ...
     288             : !> \param jparticle ...
     289             : !> \param cell ...
     290             : !> \param particle_set ...
     291             : !> \param nvec ...
     292             : !> \param energy ...
     293             : !> \param mm_section ...
     294             : !> \return ...
     295             : !> \retval angular ...
     296             : ! **************************************************************************************************
     297        5732 :    SUBROUTINE angular(anglepart, VH, gal21, r_last_update_pbc, iparticle, jparticle, cell, &
     298             :                       particle_set, nvec, energy, mm_section)
     299             :       REAL(KIND=dp)                                      :: anglepart, VH
     300             :       TYPE(gal21_pot_type), POINTER                      :: gal21
     301             :       TYPE(pos_type), DIMENSION(:), POINTER              :: r_last_update_pbc
     302             :       INTEGER, INTENT(IN)                                :: iparticle, jparticle
     303             :       TYPE(cell_type), POINTER                           :: cell
     304             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     305             :       REAL(KIND=dp), DIMENSION(3)                        :: nvec
     306             :       LOGICAL                                            :: energy
     307             :       TYPE(section_vals_type), POINTER                   :: mm_section
     308             : 
     309             :       CHARACTER(LEN=2)                                   :: element_symbol
     310             :       INTEGER                                            :: count_h, iatom, index_h1, index_h2, &
     311             :                                                             index_outfile, natom
     312             :       REAL(KIND=dp)                                      :: a1, a2, a3, a4, BH, costheta, &
     313             :                                                             h_max_dist, rih(3), rih1(3), rih2(3), &
     314             :                                                             rix(3), rjh1(3), rjh2(3), theta
     315             :       TYPE(cp_logger_type), POINTER                      :: logger
     316             : 
     317        5732 :       count_h = 0
     318        5732 :       index_h1 = 0
     319        5732 :       index_h2 = 0
     320        5732 :       h_max_dist = 2.1_dp ! 1.1 angstrom
     321        5732 :       natom = SIZE(particle_set)
     322             : 
     323     4992572 :       DO iatom = 1, natom !Loop on every atom of the system
     324             :          CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
     325     4986840 :                               element_symbol=element_symbol)
     326     4986840 :          IF (element_symbol /= "H") CYCLE !Kepp only hydrogen
     327     2590864 :          rih(:) = pbc(r_last_update_pbc(iparticle)%r(:), r_last_update_pbc(iatom)%r(:), cell)
     328    10363456 :          IF (SQRT(DOT_PRODUCT(rih, rih)) >= h_max_dist) CYCLE !Keep only hydrogen that are bounded to the considered O
     329       11464 :          count_h = count_h + 1
     330       17196 :          IF (count_h == 1) THEN
     331             :             index_h1 = iatom
     332        5732 :          ELSEIF (count_h == 2) THEN
     333        5732 :             index_h2 = iatom
     334             :          END IF
     335             :       END DO
     336             : 
     337             :       ! Abort if the oxygen is not part of a water molecule (2 H)
     338        5732 :       IF (count_h /= 2) THEN
     339             :          CALL cp_abort(__LOCATION__, &
     340           0 :                        " Error: Found "//cp_to_string(count_h)//" H atoms for O atom "//cp_to_string(iparticle))
     341             :       END IF
     342             : 
     343        5732 :       a1 = gal21%a11 + gal21%a12*gal21%gcn(jparticle) + gal21%a13*gal21%gcn(jparticle)*gal21%gcn(jparticle)
     344        5732 :       a2 = gal21%a21 + gal21%a22*gal21%gcn(jparticle) + gal21%a23*gal21%gcn(jparticle)*gal21%gcn(jparticle)
     345        5732 :       a3 = gal21%a31 + gal21%a32*gal21%gcn(jparticle) + gal21%a33*gal21%gcn(jparticle)*gal21%gcn(jparticle)
     346        5732 :       a4 = gal21%a41 + gal21%a42*gal21%gcn(jparticle) + gal21%a43*gal21%gcn(jparticle)*gal21%gcn(jparticle)
     347             : 
     348        5732 :       rih1(:) = pbc(r_last_update_pbc(iparticle)%r(:), r_last_update_pbc(index_h1)%r(:), cell)
     349        5732 :       rih2(:) = pbc(r_last_update_pbc(iparticle)%r(:), r_last_update_pbc(index_h2)%r(:), cell)
     350       22928 :       rix(:) = rih1(:) + rih2(:) ! build the dipole vector rix of the H2O molecule
     351       40124 :       costheta = DOT_PRODUCT(rix, nvec)/SQRT(DOT_PRODUCT(rix, rix))
     352        5732 :       IF (costheta < -1.0_dp) costheta = -1.0_dp
     353        5732 :       IF (costheta > +1.0_dp) costheta = +1.0_dp
     354        5732 :       theta = ACOS(costheta) ! Theta is the angle between the normal to the surface and the dipole
     355             :       anglepart = a1*costheta + a2*COS(2.0_dp*theta) + a3*COS(3.0_dp*theta) &
     356        5732 :                   + a4*COS(4.0_dp*theta) ! build the fourier series
     357             : 
     358        5732 :       BH = gal21%BH1 + gal21%gcn(jparticle)*gal21%BH2
     359             : 
     360        5732 :       rjh1(:) = pbc(r_last_update_pbc(jparticle)%r(:), r_last_update_pbc(index_h1)%r(:), cell)
     361        5732 :       rjh2(:) = pbc(r_last_update_pbc(jparticle)%r(:), r_last_update_pbc(index_h2)%r(:), cell)
     362             :       VH = (gal21%AH2*gal21%gcn(jparticle) + gal21%AH1)*(EXP(-BH*SQRT(DOT_PRODUCT(rjh1, rjh1))) + &
     363       40124 :                                                          EXP(-BH*SQRT(DOT_PRODUCT(rjh2, rjh2))))
     364             : 
     365             :       ! For fit purpose
     366        5732 :       IF (gal21%express .AND. energy) THEN
     367           0 :          logger => cp_get_default_logger()
     368             :          index_outfile = cp_print_key_unit_nr(logger, mm_section, &
     369           0 :                                               "PRINT%PROGRAM_RUN_INFO", extension=".mmLog")
     370             : 
     371           0 :          IF (index_outfile > 0) WRITE (index_outfile, *) "Fourier", costheta, COS(2.0_dp*theta), COS(3.0_dp*theta), &
     372           0 :             COS(4.0_dp*theta) !, theta
     373           0 :          IF (index_outfile > 0) WRITE (index_outfile, *) "H_rep", EXP(-BH*SQRT(DOT_PRODUCT(rjh1, rjh1))) + &
     374           0 :             EXP(-BH*SQRT(DOT_PRODUCT(rjh2, rjh2)))
     375             :          !IF (index_outfile > 0) WRITE (index_outfile, *) "H_r6", -1/DOT_PRODUCT(rjh1,rjh1)**3 -1/DOT_PRODUCT(rjh2,rjh2)**3
     376             : 
     377             :          CALL cp_print_key_finished_output(index_outfile, logger, mm_section, &
     378           0 :                                            "PRINT%PROGRAM_RUN_INFO")
     379             :       END IF
     380             : 
     381        5732 :    END SUBROUTINE
     382             : 
     383             : ! **************************************************************************************************
     384             : !> \brief forces generated by the GAL2119 potential
     385             : !> \param gal21 all parameters of GAL2119
     386             : !> \param r_last_update_pbc position of every atoms on previous frame
     387             : !> \param iparticle first index of the atom of the evaluated pair
     388             : !> \param jparticle second index of the atom of the evaluated pair
     389             : !> \param f_nonbond all the forces applying on the system
     390             : !> \param pv_nonbond ...
     391             : !> \param use_virial request of usage of virial (for barostat)
     392             : !> \param cell dimension of the pbc cell
     393             : !> \param particle_set full list of atoms of the system
     394             : !> \author Clabaut Paul - 2019 - ENS de Lyon
     395             : ! **************************************************************************************************
     396        5732 :    SUBROUTINE gal21_forces(gal21, r_last_update_pbc, iparticle, jparticle, f_nonbond, pv_nonbond, &
     397             :                            use_virial, cell, particle_set)
     398             :       TYPE(gal21_pot_type), POINTER                      :: gal21
     399             :       TYPE(pos_type), DIMENSION(:), POINTER              :: r_last_update_pbc
     400             :       INTEGER, INTENT(IN)                                :: iparticle, jparticle
     401             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: f_nonbond, pv_nonbond
     402             :       LOGICAL, INTENT(IN)                                :: use_virial
     403             :       TYPE(cell_type), POINTER                           :: cell
     404             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     405             : 
     406             :       CHARACTER(LEN=2)                                   :: element_symbol
     407             :       REAL(KIND=dp) :: anglepart, AO, BO, bxy, bz, cosalpha, dGauss(3), drji, drjicosalpha(3), &
     408             :          drjisinalpha(3), dTT(3), dweight(3), eps, nvec(3), prefactor, rji(3), rji_hat(3), &
     409             :          sinalpha, sum_weight, Vgaussian, VH, weight
     410             :       TYPE(section_vals_type), POINTER                   :: mm_section
     411             : 
     412             :       CALL get_atomic_kind(atomic_kind=particle_set(iparticle)%atomic_kind, &
     413        5732 :                            element_symbol=element_symbol)
     414             : 
     415        5732 :       IF (element_symbol == "O") THEN !To avoid counting two times each pair
     416             : 
     417        2866 :          rji(:) = pbc(r_last_update_pbc(jparticle)%r(:), r_last_update_pbc(iparticle)%r(:), cell)
     418       11464 :          drji = SQRT(DOT_PRODUCT(rji, rji))
     419       11464 :          rji_hat(:) = rji(:)/drji ! hat = pure directional component of a given vector
     420             : 
     421        2866 :          IF (.NOT. ALLOCATED(gal21%n_vectors)) THEN !First calling of the forcefield only
     422           0 :             ALLOCATE (gal21%n_vectors(3, SIZE(particle_set)))
     423           0 :             gal21%n_vectors(:, :) = 0.0_dp
     424             :          END IF
     425             : 
     426             :          !Build epsilon attraction and the a parameters of the Fourier serie as quadratic fucntion of gcn
     427        2866 :          eps = gal21%epsilon1*gal21%gcn(jparticle)*gal21%gcn(jparticle) + gal21%epsilon2*gal21%gcn(jparticle) + gal21%epsilon3
     428        2866 :          bxy = gal21%bxy1 + gal21%bxy2*gal21%gcn(jparticle)
     429        2866 :          bz = gal21%bz1 + gal21%bz2*gal21%gcn(jparticle)
     430             : 
     431             :          !Angular dependance %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     432             : 
     433             :          !Calculation of the normal vector centered on the Me atom of the pair, only the first time that an interaction with the metal atom of the pair is evaluated
     434             :          IF (gal21%n_vectors(1, jparticle) == 0.0_dp .AND. &
     435        2866 :              gal21%n_vectors(2, jparticle) == 0.0_dp .AND. &
     436             :              gal21%n_vectors(3, jparticle) == 0.0_dp) THEN
     437             :             gal21%n_vectors(:, jparticle) = normale(gal21, r_last_update_pbc, jparticle, &
     438           0 :                                                     particle_set, cell)
     439             :          END IF
     440             : 
     441       11464 :          nvec(:) = gal21%n_vectors(:, jparticle) !Else, retrive it, should not have moved sinc metal is supposed to be frozen
     442             : 
     443             :          !Calculation of the sum of the expontial weights of each Me surrounding the principal one
     444        2866 :          sum_weight = somme(gal21, r_last_update_pbc, iparticle, particle_set, cell)
     445             : 
     446             :          !Exponential damping weight for angular dependance
     447        2866 :          weight = EXP(-drji/gal21%r1)
     448       11464 :          dweight(:) = 1.0_dp/gal21%r1*weight*rji_hat(:) !Derivativ of it
     449             : 
     450             :          !Calculation of the truncated fourier series of the water-dipole/surface-normal angle
     451        2866 :          NULLIFY (mm_section)
     452             :          anglepart = 0.0_dp
     453             :          VH = 0.0_dp
     454             :          CALL angular(anglepart, VH, gal21, r_last_update_pbc, iparticle, jparticle, cell, particle_set, nvec, &
     455        2866 :                       .FALSE., mm_section)
     456             : 
     457             :          !Build the average of the exponential weight while avoiding division by 0
     458        2866 :          IF (weight /= 0) THEN
     459             :             ! Calculate the first component of the derivativ of the angular term
     460             :             f_nonbond(1:3, iparticle) = f_nonbond(1:3, iparticle) + 2.0_dp*dweight(1:3)*weight* &
     461       11464 :                                         anglepart/sum_weight
     462             : 
     463        2866 :             IF (use_virial) THEN
     464             :                pv_nonbond(1, 1:3) = pv_nonbond(1, 1:3) + rji(1)*2.0_dp*dweight(1:3)*weight* &
     465           0 :                                     anglepart/sum_weight
     466             :                pv_nonbond(2, 1:3) = pv_nonbond(2, 1:3) + rji(2)*2.0_dp*dweight(1:3)*weight* &
     467           0 :                                     anglepart/sum_weight
     468             :                pv_nonbond(3, 1:3) = pv_nonbond(3, 1:3) + rji(3)*2.0_dp*dweight(1:3)*weight* &
     469           0 :                                     anglepart/sum_weight
     470             :             END IF
     471             : 
     472             :             ! Calculate the second component of the derivativ of the angular term
     473             :             CALL somme_d(gal21, r_last_update_pbc, iparticle, jparticle, &
     474        2866 :                          f_nonbond, pv_nonbond, use_virial, particle_set, cell, anglepart, sum_weight)
     475             : 
     476        2866 :             prefactor = (-1.0_dp)*weight*weight/sum_weight ! Avoiding division by 0
     477             : 
     478             :             ! Calculate the third component of the derivativ of the angular term
     479             :             CALL angular_d(gal21, r_last_update_pbc, iparticle, jparticle, &
     480        2866 :                            f_nonbond, pv_nonbond, use_virial, prefactor, cell, particle_set, nvec)
     481             :          END IF
     482             :          !END Angular%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     483             : 
     484             :          !Attractive Gaussian %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     485             :          !Alpha is the angle of the Me-O vector with the normale vector. Used for gaussian attaction
     486       11464 :          cosalpha = DOT_PRODUCT(rji, nvec)/drji
     487        2866 :          IF (cosalpha < -1.0_dp) cosalpha = -1.0_dp
     488        2866 :          IF (cosalpha > +1.0_dp) cosalpha = +1.0_dp
     489        2866 :          sinalpha = SIN(ACOS(cosalpha))
     490             : 
     491             :          !Gaussian component of the energy
     492             :          Vgaussian = -1.0_dp*eps*EXP(-bz*DOT_PRODUCT(rji, rji)*cosalpha*cosalpha &
     493       11464 :                                      - bxy*DOT_PRODUCT(rji, rji)*sinalpha*sinalpha)
     494             : 
     495             :          ! Calculation of partial derivativ of the gaussian components
     496       11464 :          drjicosalpha(:) = rji_hat(:)*cosalpha + nvec(:) - cosalpha*rji_hat(:)
     497       11464 :          drjisinalpha(:) = rji_hat(:)*sinalpha - (cosalpha/sinalpha)*(nvec(:) - cosalpha*rji_hat(:))
     498             :          dGauss(:) = (-1.0_dp*bz*2*drji*cosalpha*drjicosalpha - &
     499       11464 :                       1.0_dp*bxy*2*drji*sinalpha*drjisinalpha)*Vgaussian*(-1.0_dp)
     500             : 
     501             :          ! Force due to gaussian term
     502       11464 :          f_nonbond(1:3, iparticle) = f_nonbond(1:3, iparticle) + dGauss(1:3)
     503             : 
     504        2866 :          IF (use_virial) THEN
     505           0 :             pv_nonbond(1, 1:3) = pv_nonbond(1, 1:3) + rji(1)*dGauss(1:3)
     506           0 :             pv_nonbond(2, 1:3) = pv_nonbond(2, 1:3) + rji(2)*dGauss(1:3)
     507           0 :             pv_nonbond(3, 1:3) = pv_nonbond(3, 1:3) + rji(3)*dGauss(1:3)
     508             :          END IF
     509             :          !END Gaussian%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     510             : 
     511        2866 :          AO = gal21%AO1 + gal21%AO2*gal21%gcn(jparticle)
     512        2866 :          BO = gal21%BO1 + gal21%BO2*gal21%gcn(jparticle)
     513             : 
     514             :          !Derivativ of the Tang and Toennies term
     515             :          dTT(:) = (-(AO*BO + (BO**7)*gal21%c/720)*EXP(-BO*drji) + 6*(gal21%c/drji**7)* &
     516             :                    (1.0 - EXP(-BO*drji) &
     517             :                     - BO*drji*EXP(-BO*drji) &
     518             :                     - (((BO*drji)**2)/2)*EXP(-BO*drji) &
     519             :                     - (((BO*drji)**3)/6)*EXP(-BO*drji) &
     520             :                     - (((BO*drji)**4)/24)*EXP(-BO*drji) &
     521             :                     - (((BO*drji)**5)/120)*EXP(-BO*drji) &
     522             :                     - (((BO*drji)**6)/720)*EXP(-BO*drji)) &
     523       11464 :                    )*rji_hat(:)
     524             : 
     525             :          ! Force of Tang & Toennies
     526       11464 :          f_nonbond(1:3, iparticle) = f_nonbond(1:3, iparticle) - dTT(1:3)
     527             : 
     528        2866 :          IF (use_virial) THEN
     529           0 :             pv_nonbond(1, 1:3) = pv_nonbond(1, 1:3) - rji(1)*dTT(1:3)
     530           0 :             pv_nonbond(2, 1:3) = pv_nonbond(2, 1:3) - rji(2)*dTT(1:3)
     531           0 :             pv_nonbond(3, 1:3) = pv_nonbond(3, 1:3) - rji(3)*dTT(1:3)
     532             :          END IF
     533             : 
     534             :       END IF
     535             : 
     536        5732 :    END SUBROUTINE gal21_forces
     537             : 
     538             : ! **************************************************************************************************
     539             : !> \brief Derivativ of the second component of angular dependance
     540             : !> \param gal21 ...
     541             : !> \param r_last_update_pbc ...
     542             : !> \param iparticle ...
     543             : !> \param jparticle ...
     544             : !> \param f_nonbond ...
     545             : !> \param pv_nonbond ...
     546             : !> \param use_virial ...
     547             : !> \param particle_set ...
     548             : !> \param cell ...
     549             : !> \param anglepart ...
     550             : !> \param sum_weight ...
     551             : ! **************************************************************************************************
     552        2866 :    SUBROUTINE somme_d(gal21, r_last_update_pbc, iparticle, jparticle, &
     553        2866 :                       f_nonbond, pv_nonbond, use_virial, particle_set, cell, anglepart, sum_weight)
     554             :       TYPE(gal21_pot_type), POINTER                      :: gal21
     555             :       TYPE(pos_type), DIMENSION(:), POINTER              :: r_last_update_pbc
     556             :       INTEGER, INTENT(IN)                                :: iparticle, jparticle
     557             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: f_nonbond, pv_nonbond
     558             :       LOGICAL, INTENT(IN)                                :: use_virial
     559             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     560             :       TYPE(cell_type), POINTER                           :: cell
     561             :       REAL(KIND=dp), INTENT(IN)                          :: anglepart, sum_weight
     562             : 
     563             :       CHARACTER(LEN=2)                                   :: element_symbol_k
     564             :       INTEGER                                            :: kparticle, natom
     565             :       REAL(KIND=dp)                                      :: drki, dwdr(3), rji(3), rki(3), &
     566             :                                                             rki_hat(3), weight_rji
     567             : 
     568        2866 :       rji(:) = pbc(r_last_update_pbc(jparticle)%r(:), r_last_update_pbc(iparticle)%r(:), cell)
     569       11464 :       weight_rji = EXP(-SQRT(DOT_PRODUCT(rji, rji))/gal21%r1)
     570             : 
     571        2866 :       natom = SIZE(particle_set)
     572     2496286 :       DO kparticle = 1, natom !Loop on every atom of the system
     573             :          CALL get_atomic_kind(atomic_kind=particle_set(kparticle)%atomic_kind, &
     574     2493420 :                               element_symbol=element_symbol_k)
     575     2493420 :          IF (element_symbol_k /= gal21%met1 .AND. element_symbol_k /= gal21%met2) CYCLE !Keep only metals
     576      550272 :          rki(:) = pbc(r_last_update_pbc(kparticle)%r(:), r_last_update_pbc(iparticle)%r(:), cell)
     577     2201088 :          IF (SQRT(DOT_PRODUCT(rki, rki)) > gal21%rcutsq) CYCLE !Keep only those within cutoff distance of the oxygen atom of the evaluated pair (the omega ensemble)
     578     2201088 :          drki = SQRT(DOT_PRODUCT(rki, rki))
     579     2201088 :          rki_hat(:) = rki(:)/drki
     580             : 
     581     2201088 :          IF (element_symbol_k == gal21%met1) dwdr(:) = (-1.0_dp)*(1.0_dp/gal21%r1)*EXP(-drki/gal21%r1)*rki_hat(:) !Build the sum of derivativs
     582      550272 :          IF (element_symbol_k == gal21%met2) dwdr(:) = (-1.0_dp)*(1.0_dp/gal21%r2)*EXP(-drki/gal21%r2)*rki_hat(:)
     583             : 
     584             :          f_nonbond(1:3, iparticle) = f_nonbond(1:3, iparticle) + dwdr(1:3)*weight_rji &
     585     2201088 :                                      *weight_rji*anglepart/(sum_weight**2)
     586             : 
     587      553138 :          IF (use_virial) THEN
     588             :             pv_nonbond(1, 1:3) = pv_nonbond(1, 1:3) + rki(1)*dwdr(1:3)*weight_rji &
     589           0 :                                  *weight_rji*anglepart/(sum_weight**2)
     590             :             pv_nonbond(2, 1:3) = pv_nonbond(2, 1:3) + rki(2)*dwdr(1:3)*weight_rji &
     591           0 :                                  *weight_rji*anglepart/(sum_weight**2)
     592             :             pv_nonbond(3, 1:3) = pv_nonbond(3, 1:3) + rki(3)*dwdr(1:3)*weight_rji &
     593           0 :                                  *weight_rji*anglepart/(sum_weight**2)
     594             :          END IF
     595             : 
     596             :       END DO
     597             : 
     598        2866 :    END SUBROUTINE somme_d
     599             : 
     600             : ! **************************************************************************************************
     601             : !> \brief Derivativ of the third component of angular term
     602             : !> \param gal21 ...
     603             : !> \param r_last_update_pbc ...
     604             : !> \param iparticle ...
     605             : !> \param jparticle ...
     606             : !> \param f_nonbond ...
     607             : !> \param pv_nonbond ...
     608             : !> \param use_virial ...
     609             : !> \param prefactor ...
     610             : !> \param cell ...
     611             : !> \param particle_set ...
     612             : !> \param nvec ...
     613             : ! **************************************************************************************************
     614        2866 :    SUBROUTINE angular_d(gal21, r_last_update_pbc, iparticle, jparticle, f_nonbond, &
     615        2866 :                         pv_nonbond, use_virial, prefactor, cell, particle_set, nvec)
     616             :       TYPE(gal21_pot_type), POINTER                      :: gal21
     617             :       TYPE(pos_type), DIMENSION(:), POINTER              :: r_last_update_pbc
     618             :       INTEGER, INTENT(IN)                                :: iparticle, jparticle
     619             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: f_nonbond, pv_nonbond
     620             :       LOGICAL, INTENT(IN)                                :: use_virial
     621             :       REAL(KIND=dp), INTENT(IN)                          :: prefactor
     622             :       TYPE(cell_type), POINTER                           :: cell
     623             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     624             :       REAL(KIND=dp), DIMENSION(3)                        :: nvec
     625             : 
     626             :       CHARACTER(LEN=2)                                   :: element_symbol
     627             :       INTEGER                                            :: count_h, iatom, index_h1, index_h2, natom
     628             :       REAL(KIND=dp)                                      :: a1, a2, a3, a4, BH, costheta, &
     629             :                                                             dsumdtheta, h_max_dist, theta
     630             :       REAL(KIND=dp), DIMENSION(3)                        :: dangular, dcostheta, rih, rih1, rih2, &
     631             :                                                             rix, rix_hat, rjh1, rjh2, rji, rji_hat
     632             : 
     633        2866 :       count_h = 0
     634        2866 :       index_h1 = 0
     635        2866 :       index_h2 = 0
     636        2866 :       h_max_dist = 2.1_dp ! 1.1 angstrom
     637        2866 :       natom = SIZE(particle_set)
     638             : 
     639     2496286 :       DO iatom = 1, natom !Loop on every atom of the system
     640             :          CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
     641     2493420 :                               element_symbol=element_symbol)
     642     2493420 :          IF (element_symbol /= "H") CYCLE !Kepp only hydrogen
     643     1295432 :          rih(:) = pbc(r_last_update_pbc(iparticle)%r(:), r_last_update_pbc(iatom)%r(:), cell)
     644     5181728 :          IF (SQRT(DOT_PRODUCT(rih, rih)) >= h_max_dist) CYCLE !Keep only hydrogen that are bounded to the considered O
     645        5732 :          count_h = count_h + 1
     646        8598 :          IF (count_h == 1) THEN
     647             :             index_h1 = iatom
     648        2866 :          ELSEIF (count_h == 2) THEN
     649        2866 :             index_h2 = iatom
     650             :          END IF
     651             :       END DO
     652             : 
     653             :       ! Abort if the oxygen is not part of a water molecule (2 H)
     654        2866 :       IF (count_h /= 2) THEN
     655             :          CALL cp_abort(__LOCATION__, &
     656           0 :                        " Error: Found "//cp_to_string(count_h)//" H atoms for O atom "//cp_to_string(iparticle))
     657             :       END IF
     658             : 
     659        2866 :       a1 = gal21%a11 + gal21%a12*gal21%gcn(jparticle) + gal21%a13*gal21%gcn(jparticle)*gal21%gcn(jparticle)
     660        2866 :       a2 = gal21%a21 + gal21%a22*gal21%gcn(jparticle) + gal21%a23*gal21%gcn(jparticle)*gal21%gcn(jparticle)
     661        2866 :       a3 = gal21%a31 + gal21%a32*gal21%gcn(jparticle) + gal21%a33*gal21%gcn(jparticle)*gal21%gcn(jparticle)
     662        2866 :       a4 = gal21%a41 + gal21%a42*gal21%gcn(jparticle) + gal21%a43*gal21%gcn(jparticle)*gal21%gcn(jparticle)
     663             : 
     664        2866 :       rji(:) = pbc(r_last_update_pbc(jparticle)%r(:), r_last_update_pbc(iparticle)%r(:), cell)
     665       20062 :       rji_hat(:) = rji(:)/SQRT(DOT_PRODUCT(rji, rji)) ! hat = pure directional component of a given vector
     666             : 
     667             :       !dipole vector rix of the H2O molecule
     668        2866 :       rih1(:) = pbc(r_last_update_pbc(iparticle)%r(:), r_last_update_pbc(index_h1)%r(:), cell)
     669        2866 :       rih2(:) = pbc(r_last_update_pbc(iparticle)%r(:), r_last_update_pbc(index_h2)%r(:), cell)
     670       11464 :       rix(:) = rih1(:) + rih2(:) ! build the dipole vector rix of the H2O molecule
     671       20062 :       rix_hat(:) = rix(:)/SQRT(DOT_PRODUCT(rix, rix)) ! hat = pure directional component of a given vector
     672       20062 :       costheta = DOT_PRODUCT(rix, nvec)/SQRT(DOT_PRODUCT(rix, rix)) ! Theta is the angle between the normal to the surface and the dipole
     673        2866 :       IF (costheta < -1.0_dp) costheta = -1.0_dp
     674        2866 :       IF (costheta > +1.0_dp) costheta = +1.0_dp
     675        2866 :       theta = ACOS(costheta) ! Theta is the angle between the normal to the surface and the dipole
     676             : 
     677             :       ! Calculation of partial derivativ of the angular components
     678             :       dsumdtheta = -1.0_dp*a1*SIN(theta) - a2*2.0_dp*SIN(2.0_dp*theta) - &
     679        2866 :                    a3*3.0_dp*SIN(3.0_dp*theta) - a4*4.0_dp*SIN(4.0_dp*theta)
     680       20062 :       dcostheta(:) = (1.0_dp/SQRT(DOT_PRODUCT(rix, rix)))*(nvec(:) - costheta*rix_hat(:))
     681       11464 :       dangular(:) = prefactor*dsumdtheta*(-1.0_dp/SIN(theta))*dcostheta(:)
     682             : 
     683             :       !Force due to the third component of the derivativ of the angular term
     684       11464 :       f_nonbond(1:3, iparticle) = f_nonbond(1:3, iparticle) - dangular(1:3)*2.0_dp !(one per H)
     685       11464 :       f_nonbond(1:3, index_h1) = f_nonbond(1:3, index_h1) + dangular(1:3)
     686       11464 :       f_nonbond(1:3, index_h2) = f_nonbond(1:3, index_h2) + dangular(1:3)
     687             : 
     688        2866 :       IF (use_virial) THEN
     689           0 :          pv_nonbond(1, 1:3) = pv_nonbond(1, 1:3) + rix(1)*dangular(1:3)
     690           0 :          pv_nonbond(2, 1:3) = pv_nonbond(2, 1:3) + rix(2)*dangular(1:3)
     691           0 :          pv_nonbond(3, 1:3) = pv_nonbond(3, 1:3) + rix(3)*dangular(1:3)
     692             :       END IF
     693             : 
     694        2866 :       BH = gal21%BH1 + gal21%gcn(jparticle)*gal21%BH2
     695             : 
     696        2866 :       rjh1(:) = pbc(r_last_update_pbc(jparticle)%r(:), r_last_update_pbc(index_h1)%r(:), cell)
     697             :       f_nonbond(1:3, index_h1) = f_nonbond(1:3, index_h1) + (gal21%AH2*gal21%gcn(jparticle) + gal21%AH1)* &
     698       20062 :                                  BH*EXP(-BH*SQRT(DOT_PRODUCT(rjh1, rjh1)))*rjh1(:)/SQRT(DOT_PRODUCT(rjh1, rjh1))
     699             : 
     700        2866 :       IF (use_virial) THEN
     701             :          pv_nonbond(1, 1:3) = pv_nonbond(1, 1:3) + rjh1(1)*((gal21%AH2*gal21%gcn(jparticle) + gal21%AH1)* &
     702             :                                                             BH*EXP(-BH*SQRT(DOT_PRODUCT(rjh1, rjh1)))) &
     703           0 :                               *rjh1(:)/SQRT(DOT_PRODUCT(rjh1, rjh1))
     704             :          pv_nonbond(2, 1:3) = pv_nonbond(2, 1:3) + rjh1(2)*((gal21%AH2*gal21%gcn(jparticle) + gal21%AH1)* &
     705             :                                                             BH*EXP(-BH*SQRT(DOT_PRODUCT(rjh1, rjh1)))) &
     706           0 :                               *rjh1(:)/SQRT(DOT_PRODUCT(rjh1, rjh1))
     707             :          pv_nonbond(3, 1:3) = pv_nonbond(3, 1:3) + rjh1(3)*((gal21%AH2*gal21%gcn(jparticle) + gal21%AH1)* &
     708             :                                                             BH*EXP(-BH*SQRT(DOT_PRODUCT(rjh1, rjh1)))) &
     709           0 :                               *rjh1(:)/SQRT(DOT_PRODUCT(rjh1, rjh1))
     710             :       END IF
     711             : 
     712        2866 :       rjh2(:) = pbc(r_last_update_pbc(jparticle)%r(:), r_last_update_pbc(index_h2)%r(:), cell)
     713             :       f_nonbond(1:3, index_h2) = f_nonbond(1:3, index_h2) + ((gal21%AH2*gal21%gcn(jparticle) + gal21%AH1)* &
     714             :                                                              BH*EXP(-BH*SQRT(DOT_PRODUCT(rjh2, rjh2)))) &
     715       20062 :                                  *rjh2(:)/SQRT(DOT_PRODUCT(rjh2, rjh2))
     716             : 
     717        2866 :       IF (use_virial) THEN
     718             :          pv_nonbond(1, 1:3) = pv_nonbond(1, 1:3) + rjh2(1)*((gal21%AH2*gal21%gcn(jparticle) + gal21%AH1)* &
     719             :                                                             BH*EXP(-BH*SQRT(DOT_PRODUCT(rjh2, rjh2)))) &
     720           0 :                               *rjh2(:)/SQRT(DOT_PRODUCT(rjh2, rjh2))
     721             :          pv_nonbond(2, 1:3) = pv_nonbond(2, 1:3) + rjh2(2)*((gal21%AH2*gal21%gcn(jparticle) + gal21%AH1)* &
     722             :                                                             BH*EXP(-BH*SQRT(DOT_PRODUCT(rjh2, rjh2)))) &
     723           0 :                               *rjh2(:)/SQRT(DOT_PRODUCT(rjh2, rjh2))
     724             :          pv_nonbond(3, 1:3) = pv_nonbond(3, 1:3) + rjh2(3)*((gal21%AH2*gal21%gcn(jparticle) + gal21%AH1)* &
     725             :                                                             BH*EXP(-BH*SQRT(DOT_PRODUCT(rjh2, rjh2)))) &
     726           0 :                               *rjh2(:)/SQRT(DOT_PRODUCT(rjh2, rjh2))
     727             :       END IF
     728             : 
     729        2866 :    END SUBROUTINE angular_d
     730             : 
     731             : ! **************************************************************************************************
     732             : !> \brief ...
     733             : !> \param nonbonded ...
     734             : !> \param potparm ...
     735             : !> \param glob_loc_list ...
     736             : !> \param glob_cell_v ...
     737             : !> \param glob_loc_list_a ...
     738             : !> \param cell ...
     739             : !> \par History
     740             : ! **************************************************************************************************
     741           2 :    SUBROUTINE setup_gal21_arrays(nonbonded, potparm, glob_loc_list, glob_cell_v, &
     742             :                                  glob_loc_list_a, cell)
     743             :       TYPE(fist_neighbor_type), POINTER                  :: nonbonded
     744             :       TYPE(pair_potential_pp_type), POINTER              :: potparm
     745             :       INTEGER, DIMENSION(:, :), POINTER                  :: glob_loc_list
     746             :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: glob_cell_v
     747             :       INTEGER, DIMENSION(:), POINTER                     :: glob_loc_list_a
     748             :       TYPE(cell_type), POINTER                           :: cell
     749             : 
     750             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'setup_gal21_arrays'
     751             : 
     752             :       INTEGER                                            :: handle, i, iend, igrp, ikind, ilist, &
     753             :                                                             ipair, istart, jkind, nkinds, npairs, &
     754             :                                                             npairs_tot
     755           2 :       INTEGER, DIMENSION(:), POINTER                     :: work_list, work_list2
     756           2 :       INTEGER, DIMENSION(:, :), POINTER                  :: list
     757             :       REAL(KIND=dp), DIMENSION(3)                        :: cell_v, cvi
     758           2 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rwork_list
     759             :       TYPE(neighbor_kind_pairs_type), POINTER            :: neighbor_kind_pair
     760             :       TYPE(pair_potential_single_type), POINTER          :: pot
     761             : 
     762           0 :       CPASSERT(.NOT. ASSOCIATED(glob_loc_list))
     763           2 :       CPASSERT(.NOT. ASSOCIATED(glob_loc_list_a))
     764           2 :       CPASSERT(.NOT. ASSOCIATED(glob_cell_v))
     765           2 :       CALL timeset(routineN, handle)
     766           2 :       npairs_tot = 0
     767           2 :       nkinds = SIZE(potparm%pot, 1)
     768          56 :       DO ilist = 1, nonbonded%nlists
     769          54 :          neighbor_kind_pair => nonbonded%neighbor_kind_pairs(ilist)
     770          54 :          npairs = neighbor_kind_pair%npairs
     771          54 :          IF (npairs == 0) CYCLE
     772         336 :          Kind_Group_Loop1: DO igrp = 1, neighbor_kind_pair%ngrp_kind
     773         316 :             istart = neighbor_kind_pair%grp_kind_start(igrp)
     774         316 :             iend = neighbor_kind_pair%grp_kind_end(igrp)
     775         316 :             ikind = neighbor_kind_pair%ij_kind(1, igrp)
     776         316 :             jkind = neighbor_kind_pair%ij_kind(2, igrp)
     777         316 :             pot => potparm%pot(ikind, jkind)%pot
     778         316 :             npairs = iend - istart + 1
     779         316 :             IF (pot%no_mb) CYCLE
     780          90 :             DO i = 1, SIZE(pot%type)
     781         334 :                IF (pot%type(i) == gal21_type) npairs_tot = npairs_tot + npairs
     782             :             END DO
     783             :          END DO Kind_Group_Loop1
     784             :       END DO
     785           6 :       ALLOCATE (work_list(npairs_tot))
     786           4 :       ALLOCATE (work_list2(npairs_tot))
     787           6 :       ALLOCATE (glob_loc_list(2, npairs_tot))
     788           6 :       ALLOCATE (glob_cell_v(3, npairs_tot))
     789             :       ! Fill arrays with data
     790           2 :       npairs_tot = 0
     791          56 :       DO ilist = 1, nonbonded%nlists
     792          54 :          neighbor_kind_pair => nonbonded%neighbor_kind_pairs(ilist)
     793          54 :          npairs = neighbor_kind_pair%npairs
     794          54 :          IF (npairs == 0) CYCLE
     795         336 :          Kind_Group_Loop2: DO igrp = 1, neighbor_kind_pair%ngrp_kind
     796         316 :             istart = neighbor_kind_pair%grp_kind_start(igrp)
     797         316 :             iend = neighbor_kind_pair%grp_kind_end(igrp)
     798         316 :             ikind = neighbor_kind_pair%ij_kind(1, igrp)
     799         316 :             jkind = neighbor_kind_pair%ij_kind(2, igrp)
     800         316 :             list => neighbor_kind_pair%list
     801        1264 :             cvi = neighbor_kind_pair%cell_vector
     802         316 :             pot => potparm%pot(ikind, jkind)%pot
     803         316 :             npairs = iend - istart + 1
     804         316 :             IF (pot%no_mb) CYCLE
     805         234 :             cell_v = MATMUL(cell%hmat, cvi)
     806          90 :             DO i = 1, SIZE(pot%type)
     807             :                ! gal21
     808         334 :                IF (pot%type(i) == gal21_type) THEN
     809       17618 :                   DO ipair = 1, npairs
     810      105600 :                      glob_loc_list(:, npairs_tot + ipair) = list(:, istart - 1 + ipair)
     811       70418 :                      glob_cell_v(1:3, npairs_tot + ipair) = cell_v(1:3)
     812             :                   END DO
     813          18 :                   npairs_tot = npairs_tot + npairs
     814             :                END IF
     815             :             END DO
     816             :          END DO Kind_Group_Loop2
     817             :       END DO
     818             :       ! Order the arrays w.r.t. the first index of glob_loc_list
     819           2 :       CALL sort(glob_loc_list(1, :), npairs_tot, work_list)
     820       17602 :       DO ipair = 1, npairs_tot
     821       17602 :          work_list2(ipair) = glob_loc_list(2, work_list(ipair))
     822             :       END DO
     823       35204 :       glob_loc_list(2, :) = work_list2
     824           2 :       DEALLOCATE (work_list2)
     825           6 :       ALLOCATE (rwork_list(3, npairs_tot))
     826       17602 :       DO ipair = 1, npairs_tot
     827      140802 :          rwork_list(:, ipair) = glob_cell_v(:, work_list(ipair))
     828             :       END DO
     829      140804 :       glob_cell_v = rwork_list
     830           2 :       DEALLOCATE (rwork_list)
     831           2 :       DEALLOCATE (work_list)
     832           6 :       ALLOCATE (glob_loc_list_a(npairs_tot))
     833       35204 :       glob_loc_list_a = glob_loc_list(1, :)
     834           2 :       CALL timestop(handle)
     835           4 :    END SUBROUTINE setup_gal21_arrays
     836             : 
     837             : ! **************************************************************************************************
     838             : !> \brief ...
     839             : !> \param glob_loc_list ...
     840             : !> \param glob_cell_v ...
     841             : !> \param glob_loc_list_a ...
     842             : ! **************************************************************************************************
     843           1 :    SUBROUTINE destroy_gal21_arrays(glob_loc_list, glob_cell_v, glob_loc_list_a)
     844             :       INTEGER, DIMENSION(:, :), POINTER                  :: glob_loc_list
     845             :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: glob_cell_v
     846             :       INTEGER, DIMENSION(:), POINTER                     :: glob_loc_list_a
     847             : 
     848           1 :       IF (ASSOCIATED(glob_loc_list)) THEN
     849           1 :          DEALLOCATE (glob_loc_list)
     850             :       END IF
     851           1 :       IF (ASSOCIATED(glob_loc_list_a)) THEN
     852           1 :          DEALLOCATE (glob_loc_list_a)
     853             :       END IF
     854           1 :       IF (ASSOCIATED(glob_cell_v)) THEN
     855           1 :          DEALLOCATE (glob_cell_v)
     856             :       END IF
     857             : 
     858           1 :    END SUBROUTINE destroy_gal21_arrays
     859             : 
     860             : ! **************************************************************************************************
     861             : !> \brief prints the number of OH- ions or H3O+ ions near surface
     862             : !> \param nr_ions number of ions
     863             : !> \param mm_section ...
     864             : !> \param para_env ...
     865             : !> \param print_oh flag indicating if number OH- is printed
     866             : !> \param print_h3o flag indicating if number H3O+ is printed
     867             : !> \param print_o flag indicating if number O^(2-) is printed
     868             : ! **************************************************************************************************
     869           0 :    SUBROUTINE print_nr_ions_gal21(nr_ions, mm_section, para_env, print_oh, &
     870             :                                   print_h3o, print_o)
     871             :       INTEGER, INTENT(INOUT)                             :: nr_ions
     872             :       TYPE(section_vals_type), POINTER                   :: mm_section
     873             :       TYPE(mp_para_env_type), OPTIONAL, POINTER          :: para_env
     874             :       LOGICAL, INTENT(IN)                                :: print_oh, print_h3o, print_o
     875             : 
     876             :       INTEGER                                            :: iw
     877             :       TYPE(cp_logger_type), POINTER                      :: logger
     878             : 
     879           0 :       NULLIFY (logger)
     880             : 
     881           0 :       CALL para_env%sum(nr_ions)
     882           0 :       logger => cp_get_default_logger()
     883             : 
     884             :       iw = cp_print_key_unit_nr(logger, mm_section, "PRINT%PROGRAM_RUN_INFO", &
     885           0 :                                 extension=".mmLog")
     886             : 
     887           0 :       IF (iw > 0 .AND. nr_ions > 0 .AND. print_oh) THEN
     888           0 :          WRITE (iw, '(/,A,T71,I10,/)') " gal21: number of OH- ions at surface", nr_ions
     889             :       END IF
     890           0 :       IF (iw > 0 .AND. nr_ions > 0 .AND. print_h3o) THEN
     891           0 :          WRITE (iw, '(/,A,T71,I10,/)') " gal21: number of H3O+ ions at surface", nr_ions
     892             :       END IF
     893           0 :       IF (iw > 0 .AND. nr_ions > 0 .AND. print_o) THEN
     894           0 :          WRITE (iw, '(/,A,T71,I10,/)') " gal21: number of O^2- ions at surface", nr_ions
     895             :       END IF
     896             : 
     897           0 :       CALL cp_print_key_finished_output(iw, logger, mm_section, "PRINT%PROGRAM_RUN_INFO")
     898             : 
     899           0 :    END SUBROUTINE print_nr_ions_gal21
     900             : 
     901             : END MODULE manybody_gal21

Generated by: LCOV version 1.15