LCOV - code coverage report
Current view: top level - src - fp_methods.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 86 97 88.7 %
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             : ! **************************************************************************************************
       9             : !> \brief methods used in the flexible partitioning scheme
      10             : !> \par History
      11             : !>      04.2006 [Joost VandeVondele]
      12             : !> \author Joost VandeVondele
      13             : ! **************************************************************************************************
      14             : MODULE fp_methods
      15             : 
      16             :    USE beta_gamma_psi,                  ONLY: psi
      17             :    USE cell_types,                      ONLY: cell_type,&
      18             :                                               pbc
      19             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      20             :                                               cp_logger_type
      21             :    USE cp_output_handling,              ONLY: cp_iter_string,&
      22             :                                               cp_print_key_finished_output,&
      23             :                                               cp_print_key_unit_nr
      24             :    USE cp_subsys_types,                 ONLY: cp_subsys_get,&
      25             :                                               cp_subsys_type
      26             :    USE fp_types,                        ONLY: fp_type
      27             :    USE kinds,                           ONLY: dp
      28             :    USE mathconstants,                   ONLY: fac,&
      29             :                                               maxfac,&
      30             :                                               oorootpi
      31             :    USE particle_list_types,             ONLY: particle_list_type
      32             :    USE particle_types,                  ONLY: particle_type
      33             : #include "./base/base_uses.f90"
      34             : 
      35             :    IMPLICIT NONE
      36             :    PRIVATE
      37             : 
      38             :    PUBLIC :: fp_eval
      39             : 
      40             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'fp_methods'
      41             : 
      42             : CONTAINS
      43             : 
      44             : ! **************************************************************************************************
      45             : !> \brief computest the forces and the energy due to the flexible potential & bias,
      46             : !>     and writes the weights file
      47             : !> \param fp_env ...
      48             : !> \param subsys ...
      49             : !> \param cell ...
      50             : !> \par History
      51             : !>      04.2006 created [Joost VandeVondele]
      52             : ! **************************************************************************************************
      53         122 :    SUBROUTINE fp_eval(fp_env, subsys, cell)
      54             :       TYPE(fp_type), POINTER                             :: fp_env
      55             :       TYPE(cp_subsys_type), POINTER                      :: subsys
      56             :       TYPE(cell_type), POINTER                           :: cell
      57             : 
      58             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'fp_eval'
      59             : 
      60             :       CHARACTER(LEN=15)                                  :: tmpstr
      61             :       INTEGER                                            :: handle, i, icenter, iparticle, &
      62             :                                                             output_unit
      63             :       LOGICAL                                            :: zero_weight
      64             :       REAL(KIND=dp)                                      :: c, dcdr, kT, r, rab(3), sf, strength
      65             :       TYPE(cp_logger_type), POINTER                      :: logger
      66             :       TYPE(particle_list_type), POINTER                  :: particles_list
      67         122 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particles
      68             : 
      69         122 :       CALL timeset(routineN, handle)
      70             : 
      71         122 :       CPASSERT(ASSOCIATED(fp_env))
      72         122 :       CPASSERT(fp_env%use_fp)
      73         122 :       CPASSERT(ASSOCIATED(subsys))
      74         122 :       CALL cp_subsys_get(subsys, particles=particles_list)
      75         122 :       particles => particles_list%els
      76             : 
      77             :       ! compute the force due to the reflecting walls
      78             :       ! and count the distribution in discrete and contiguous ways
      79         122 :       zero_weight = .FALSE.
      80         122 :       fp_env%restraint_energy = 0.0_dp
      81         122 :       icenter = fp_env%central_atom
      82         122 :       strength = fp_env%strength
      83         122 :       fp_env%i1 = 0; fp_env%i2 = 0; fp_env%o1 = 0; fp_env%o2 = 0
      84         122 :       fp_env%ri1 = 0.0_dp; fp_env%ri2 = 0.0_dp; fp_env%ro1 = 0.0_dp; fp_env%ro2 = 0.0_dp
      85         122 :       fp_env%energy = 0.0_dp
      86             : 
      87             :       ! inner particles
      88        1098 :       DO i = 1, SIZE(fp_env%inner_atoms)
      89         976 :          iparticle = fp_env%inner_atoms(i)
      90        3904 :          rab = particles(iparticle)%r - particles(icenter)%r
      91        3904 :          rab = pbc(rab, cell)
      92        3904 :          r = SQRT(SUM(rab**2))
      93             :          ! constraint wall  (they feel to outer wall)
      94         976 :          IF (r > fp_env%outer_radius) THEN
      95           0 :             zero_weight = .TRUE.
      96           0 :             fp_env%restraint_energy = fp_env%restraint_energy + 0.5_dp*strength*(r - fp_env%outer_radius)**2
      97           0 :             sf = strength*(r - fp_env%outer_radius)/r
      98           0 :             particles(iparticle)%f = particles(iparticle)%f - sf*rab
      99           0 :             particles(icenter)%f = particles(icenter)%f + sf*rab
     100             :          END IF
     101             :          ! count the distribution
     102         976 :          IF (r > fp_env%inner_radius) THEN
     103         610 :             fp_env%i2 = fp_env%i2 + 1
     104             :          ELSE
     105         366 :             fp_env%i1 = fp_env%i1 + 1
     106             :          END IF
     107             :          ! smooth count the distribution
     108         976 :          CALL smooth_count(r, fp_env%inner_radius, fp_env%smooth_width, c, dcdr)
     109         976 :          fp_env%ri1 = fp_env%ri1 + c
     110        1098 :          fp_env%ri2 = fp_env%ri2 + (1.0_dp - c)
     111             :       END DO
     112             : 
     113             :       ! outer particles
     114        2928 :       DO i = 1, SIZE(fp_env%outer_atoms)
     115        2806 :          iparticle = fp_env%outer_atoms(i)
     116       11224 :          rab = particles(iparticle)%r - particles(icenter)%r
     117       11224 :          rab = pbc(rab, cell)
     118       11224 :          r = SQRT(SUM(rab**2))
     119             :          ! constraint wall (they feel the inner wall)
     120        2806 :          IF (r < fp_env%inner_radius) THEN
     121           0 :             zero_weight = .TRUE.
     122             :             fp_env%restraint_energy = fp_env%restraint_energy + &
     123           0 :                                       0.5_dp*strength*(r - fp_env%inner_radius)**2
     124           0 :             sf = strength*(r - fp_env%inner_radius)/r
     125           0 :             particles(iparticle)%f = particles(iparticle)%f - sf*rab
     126           0 :             particles(icenter)%f = particles(icenter)%f + sf*rab
     127             :          END IF
     128             :          ! count the distribution
     129        2806 :          IF (r > fp_env%outer_radius) THEN
     130        1998 :             fp_env%o2 = fp_env%o2 + 1
     131             :          ELSE
     132         808 :             fp_env%o1 = fp_env%o1 + 1
     133             :          END IF
     134             :          ! smooth count the distribution
     135        2806 :          CALL smooth_count(r, fp_env%outer_radius, fp_env%smooth_width, c, dcdr)
     136        2806 :          fp_env%ro1 = fp_env%ro1 + c
     137        2928 :          fp_env%ro2 = fp_env%ro2 + (1.0_dp - c)
     138             :       END DO
     139         122 :       fp_env%energy = fp_env%energy + fp_env%restraint_energy
     140             : 
     141             :       ! the combinatorial weight
     142         122 :       i = fp_env%i2 + fp_env%o1
     143         122 :       CPASSERT(i <= maxfac)
     144         122 :       fp_env%comb_weight = (fac(fp_env%i2)*fac(fp_env%o1))/fac(i)
     145             : 
     146             :       ! we can add the bias potential now.
     147             :       ! this bias has the form
     148             :       ! kT * { ln[(o1+i2)!] - ln[o1!] - ln[i2!] }
     149             :       ! where the smooth counts are used for o1 and i2
     150         122 :       fp_env%bias_energy = 0.0_dp
     151         122 :       IF (fp_env%bias) THEN
     152         122 :          kT = fp_env%temperature
     153             :          fp_env%bias_energy = kT*(LOG_GAMMA(fp_env%ro1 + fp_env%ri2 + 1) - &
     154         122 :                                   LOG_GAMMA(fp_env%ro1 + 1) - LOG_GAMMA(fp_env%ri2 + 1))
     155             : 
     156             :          ! and add the corresponding forces
     157             :          ! inner particles
     158        1098 :          DO i = 1, SIZE(fp_env%inner_atoms)
     159         976 :             iparticle = fp_env%inner_atoms(i)
     160        3904 :             rab = particles(iparticle)%r - particles(icenter)%r
     161        3904 :             rab = pbc(rab, cell)
     162        3904 :             r = SQRT(SUM(rab**2))
     163         976 :             CALL smooth_count(r, fp_env%inner_radius, fp_env%smooth_width, c, dcdr)
     164         976 :             sf = kT*(psi(fp_env%ro1 + fp_env%ri2 + 1) - psi(fp_env%ri2 + 1))*(-dcdr)/r
     165        3904 :             particles(iparticle)%f = particles(iparticle)%f - sf*rab
     166        5002 :             particles(icenter)%f = particles(icenter)%f + sf*rab
     167             :          END DO
     168             :          ! outer particles
     169        2928 :          DO i = 1, SIZE(fp_env%outer_atoms)
     170        2806 :             iparticle = fp_env%outer_atoms(i)
     171       11224 :             rab = particles(iparticle)%r - particles(icenter)%r
     172       11224 :             rab = pbc(rab, cell)
     173       11224 :             r = SQRT(SUM(rab**2))
     174        2806 :             CALL smooth_count(r, fp_env%outer_radius, fp_env%smooth_width, c, dcdr)
     175        2806 :             sf = kT*(psi(fp_env%ro1 + fp_env%ri2 + 1) - psi(fp_env%ro1 + 1))*(dcdr)/r
     176       11224 :             particles(iparticle)%f = particles(iparticle)%f - sf*rab
     177       14152 :             particles(icenter)%f = particles(icenter)%f + sf*rab
     178             :          END DO
     179             :       END IF
     180         122 :       fp_env%energy = fp_env%energy + fp_env%bias_energy
     181         122 :       fp_env%bias_weight = EXP(fp_env%bias_energy/kT)
     182             : 
     183             :       ! if this configuration is a valid one, compute its weight
     184         122 :       IF (zero_weight) THEN
     185           0 :          fp_env%weight = 0.0_dp
     186             :       ELSE
     187         122 :          fp_env%weight = fp_env%comb_weight*fp_env%bias_weight
     188             :       END IF
     189             : 
     190             :       ! put weights and other info on file
     191         122 :       logger => cp_get_default_logger()
     192             :       output_unit = cp_print_key_unit_nr(logger, fp_env%print_section, "", &
     193         122 :                                          extension=".weights")
     194         122 :       IF (output_unit > 0) THEN
     195          61 :          tmpstr = cp_iter_string(logger%iter_info, fp_env%print_section)
     196             :          WRITE (output_unit, '(T2,A15,6(1X,F16.10),4(1X,I4),4(1X,F16.10))') &
     197          61 :             tmpstr, &
     198          61 :             fp_env%weight, fp_env%comb_weight, fp_env%bias_weight, &
     199          61 :             fp_env%energy, fp_env%restraint_energy, fp_env%bias_energy, &
     200          61 :             fp_env%i1, fp_env%i2, fp_env%o1, fp_env%o2, &
     201         122 :             fp_env%ri1, fp_env%ri2, fp_env%ro1, fp_env%ro2
     202             :       END IF
     203             : 
     204             :       CALL cp_print_key_finished_output(output_unit, logger, fp_env%print_section, &
     205         122 :                                         "")
     206             : 
     207         122 :       CALL timestop(handle)
     208             : 
     209         122 :    END SUBROUTINE fp_eval
     210             : 
     211             : ! **************************************************************************************************
     212             : !> \brief counts in a smooth way (error function with width=width)
     213             : !>      if r is closer than r1. Returns 1.0 for the count=c if r<<r1
     214             : !>      and the derivative wrt r dcdr
     215             : !> \param r ...
     216             : !> \param r1 ...
     217             : !> \param width ...
     218             : !> \param c ...
     219             : !> \param dcdr ...
     220             : !> \par History
     221             : !>      04.2006 created [Joost VandeVondele]
     222             : ! **************************************************************************************************
     223        7564 :    SUBROUTINE smooth_count(r, r1, width, c, dcdr)
     224             :       REAL(KIND=dp), INTENT(IN)                          :: r, r1, width
     225             :       REAL(KIND=dp), INTENT(OUT)                         :: c, dcdr
     226             : 
     227             :       REAL(KIND=dp)                                      :: arg
     228             : 
     229        7564 :       arg = (r1 - r)/width
     230             : 
     231        7564 :       c = (1.0_dp + ERF(arg))/2.0_dp
     232        7564 :       dcdr = (-oorootpi/width)*EXP(-arg**2)
     233             : 
     234        7564 :    END SUBROUTINE
     235             : 
     236             : END MODULE fp_methods

Generated by: LCOV version 1.15