LCOV - code coverage report
Current view: top level - src - metadynamics.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 453 470 96.4 %
Date: 2024-12-21 06:28:57 Functions: 8 8 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 Performs the metadynamics calculation
      10             : !> \par History
      11             : !>      01.2005 created [fawzi and ale]
      12             : !>      11.2007 Teodoro Laino [tlaino] - University of Zurich
      13             : ! **************************************************************************************************
      14             : MODULE metadynamics
      15             :    USE cp_log_handling, ONLY: cp_logger_type, cp_get_default_logger
      16             :    USE bibliography, ONLY: VandenCic2006
      17             : #if defined (__PLUMED2)
      18             :    USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE, C_CHAR
      19             :    USE cell_types, ONLY: cell_type, &
      20             :                          pbc_cp2k_plumed_getset_cell
      21             : #else
      22             :    USE cell_types, ONLY: cell_type
      23             : #endif
      24             :    USE colvar_methods, ONLY: colvar_eval_glob_f
      25             :    USE colvar_types, ONLY: colvar_p_type, &
      26             :                            torsion_colvar_id
      27             :    USE constraint_fxd, ONLY: fix_atom_control
      28             :    USE cp_output_handling, ONLY: cp_add_iter_level, &
      29             :                                  cp_iterate, &
      30             :                                  cp_print_key_finished_output, &
      31             :                                  cp_print_key_unit_nr, &
      32             :                                  cp_rm_iter_level
      33             :    USE cp_subsys_types, ONLY: cp_subsys_get, &
      34             :                               cp_subsys_type
      35             :    USE force_env_types, ONLY: force_env_get, &
      36             :                               force_env_type
      37             :    USE input_constants, ONLY: do_wall_m, &
      38             :                               do_wall_p, &
      39             :                               do_wall_reflective
      40             :    USE input_section_types, ONLY: section_vals_get, &
      41             :                                   section_vals_get_subs_vals, &
      42             :                                   section_vals_type, &
      43             :                                   section_vals_val_get
      44             :    USE kinds, ONLY: dp
      45             :    USE message_passing, ONLY: cp2k_is_parallel
      46             :    USE metadynamics_types, ONLY: hills_env_type, &
      47             :                                  meta_env_type, &
      48             :                                  metavar_type, &
      49             :                                  multiple_walkers_type
      50             :    USE metadynamics_utils, ONLY: add_hill_single, &
      51             :                                  get_meta_iter_level, &
      52             :                                  meta_walls, &
      53             :                                  restart_hills, &
      54             :                                  synchronize_multiple_walkers
      55             :    USE particle_list_types, ONLY: particle_list_type
      56             : #if defined (__PLUMED2)
      57             :    USE physcon, ONLY: angstrom, &
      58             :                       boltzmann, &
      59             :                       femtoseconds, &
      60             :                       joule, &
      61             :                       kelvin, kjmol, &
      62             :                       picoseconds
      63             : #else
      64             :    USE physcon, ONLY: boltzmann, &
      65             :                       femtoseconds, &
      66             :                       joule, &
      67             :                       kelvin
      68             : #endif
      69             :    USE reference_manager, ONLY: cite_reference
      70             :    USE simpar_types, ONLY: simpar_type
      71             : #include "./base/base_uses.f90"
      72             : 
      73             :    IMPLICIT NONE
      74             :    PRIVATE
      75             : 
      76             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'metadynamics'
      77             : 
      78             :    PUBLIC :: metadyn_forces, metadyn_integrator
      79             :    PUBLIC :: metadyn_velocities_colvar, metadyn_write_colvar
      80             :    PUBLIC :: metadyn_initialise_plumed, metadyn_finalise_plumed
      81             : 
      82             : #if defined (__PLUMED2)
      83             :    INTERFACE
      84             :       FUNCTION plumed_installed() RESULT(res) BIND(C, name="plumed_installed")
      85             :          IMPORT :: C_INT
      86             :          INTEGER(KIND=C_INT)  :: res
      87             :       END FUNCTION plumed_installed
      88             : 
      89             :       SUBROUTINE plumed_gcreate() BIND(C, name="plumed_gcreate")
      90             :       END SUBROUTINE plumed_gcreate
      91             : 
      92             :       SUBROUTINE plumed_gfinalize() BIND(C, name="plumed_gfinalize")
      93             :       END SUBROUTINE plumed_gfinalize
      94             : 
      95             :       SUBROUTINE plumed_gcmd_int(key, value) BIND(C, name="plumed_gcmd")
      96             :          IMPORT :: C_CHAR, C_INT
      97             :          CHARACTER(KIND=C_CHAR), DIMENSION(*)     :: key
      98             :          INTEGER(KIND=C_INT)                      :: value
      99             :       END SUBROUTINE plumed_gcmd_int
     100             : 
     101             :       SUBROUTINE plumed_gcmd_double(key, value) BIND(C, name="plumed_gcmd")
     102             :          IMPORT :: C_CHAR, C_DOUBLE
     103             :          CHARACTER(KIND=C_CHAR), DIMENSION(*)     :: key
     104             :          REAL(KIND=C_DOUBLE)                      :: value
     105             :       END SUBROUTINE plumed_gcmd_double
     106             : 
     107             :       SUBROUTINE plumed_gcmd_doubles(key, value) BIND(C, name="plumed_gcmd")
     108             :          IMPORT :: C_CHAR, C_DOUBLE
     109             :          CHARACTER(KIND=C_CHAR), DIMENSION(*)     :: key
     110             :          REAL(KIND=C_DOUBLE), DIMENSION(*)        :: value
     111             :       END SUBROUTINE plumed_gcmd_doubles
     112             : 
     113             :       SUBROUTINE plumed_gcmd_char(key, value) BIND(C, name="plumed_gcmd")
     114             :          IMPORT :: C_CHAR
     115             :          CHARACTER(KIND=C_CHAR), DIMENSION(*)     :: key, value
     116             :       END SUBROUTINE plumed_gcmd_char
     117             :    END INTERFACE
     118             : #endif
     119             : 
     120             : CONTAINS
     121             : 
     122             : ! **************************************************************************************************
     123             : !> \brief ...
     124             : !> \param force_env ...
     125             : !> \param simpar ...
     126             : !> \param itimes ...
     127             : ! **************************************************************************************************
     128           2 :    SUBROUTINE metadyn_initialise_plumed(force_env, simpar, itimes)
     129             : 
     130             :       TYPE(force_env_type), POINTER            :: force_env
     131             :       TYPE(simpar_type), POINTER               :: simpar
     132             :       INTEGER, INTENT(IN)                      :: itimes
     133             : 
     134             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'metadyn_initialise_plumed'
     135             : 
     136             :       INTEGER                                  :: handle
     137             : 
     138             : #if defined (__PLUMED2)
     139             :       INTEGER                                  :: natom_plumed
     140             :       REAL(KIND=dp)                            :: timestep_plumed
     141             :       TYPE(cell_type), POINTER                 :: cell
     142             :       TYPE(cp_subsys_type), POINTER            :: subsys
     143             : #endif
     144             : 
     145             : #if defined (__PLUMED2)
     146             :       INTEGER :: plumedavailable
     147             : #endif
     148             : 
     149           2 :       CALL timeset(routineN, handle)
     150           2 :       CPASSERT(ASSOCIATED(force_env))
     151           2 :       CPASSERT(ASSOCIATED(simpar))
     152             : 
     153             : #if defined (__PLUMED2)
     154           2 :       NULLIFY (cell, subsys)
     155           2 :       CALL force_env_get(force_env, subsys=subsys, cell=cell)
     156           2 :       CALL pbc_cp2k_plumed_getset_cell(cell, set=.TRUE.) !Store the cell pointer for later use.
     157           2 :       timestep_plumed = simpar%dt
     158           2 :       natom_plumed = subsys%particles%n_els
     159             : #else
     160             :       MARK_USED(force_env)
     161             :       MARK_USED(simpar)
     162             : #endif
     163             : 
     164             :       MARK_USED(itimes)
     165             : #if defined (__PLUMED2)
     166           2 :       plumedavailable = plumed_installed()
     167             : 
     168           2 :       IF (plumedavailable <= 0) THEN
     169           0 :          CPABORT("NO PLUMED IN YOUR LD_LIBRARY_PATH?")
     170             :       ELSE
     171           2 :          CALL plumed_gcreate()
     172           2 :          IF (cp2k_is_parallel) CALL plumed_gcmd_int("setMPIFComm"//CHAR(0), force_env%para_env%get_handle())
     173           2 :          CALL plumed_gcmd_int("setRealPrecision"//CHAR(0), 8)
     174           2 :          CALL plumed_gcmd_double("setMDEnergyUnits"//CHAR(0), kjmol) ! Hartree to kjoule/mol
     175           2 :          CALL plumed_gcmd_double("setMDLengthUnits"//CHAR(0), angstrom*0.1_dp) ! Bohr to nm
     176           2 :          CALL plumed_gcmd_double("setMDTimeUnits"//CHAR(0), picoseconds) !  atomic units to ps
     177           2 :          CALL plumed_gcmd_char("setPlumedDat"//CHAR(0), force_env%meta_env%plumed_input_file//CHAR(0))
     178           2 :          CALL plumed_gcmd_char("setLogFile"//CHAR(0), "PLUMED.OUT"//CHAR(0))
     179           2 :          CALL plumed_gcmd_int("setNatoms"//CHAR(0), natom_plumed)
     180           2 :          CALL plumed_gcmd_char("setMDEngine"//CHAR(0), "cp2k"//CHAR(0))
     181           2 :          CALL plumed_gcmd_double("setTimestep"//CHAR(0), timestep_plumed)
     182           2 :          CALL plumed_gcmd_int("init"//CHAR(0), 0)
     183             :       END IF
     184             : #endif
     185             : 
     186             : #if !defined (__PLUMED2)
     187             :       CALL cp_abort(__LOCATION__, &
     188             :                     "Requested to use plumed for metadynamics, but cp2k was"// &
     189             :                     " not compiled with plumed support.")
     190             : #endif
     191             : 
     192           2 :       CALL timestop(handle)
     193             : 
     194           2 :    END SUBROUTINE
     195             : 
     196             : ! **************************************************************************************************
     197             : !> \brief makes sure PLUMED is shut down cleanly
     198             : ! **************************************************************************************************
     199           2 :    SUBROUTINE metadyn_finalise_plumed()
     200             : 
     201             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'metadyn_finalise_plumed'
     202             : 
     203             :       INTEGER                                            :: handle
     204             : 
     205           2 :       CALL timeset(routineN, handle)
     206             : 
     207             : #if defined (__PLUMED2)
     208           2 :       CALL plumed_gfinalize()
     209             : #endif
     210             : 
     211           2 :       CALL timestop(handle)
     212             : 
     213           2 :    END SUBROUTINE
     214             : 
     215             : ! **************************************************************************************************
     216             : !> \brief  General driver for applying metadynamics
     217             : !> \param force_env ...
     218             : !> \param itimes ...
     219             : !> \param vel ...
     220             : !> \param rand ...
     221             : !> \date   01.2009
     222             : !> \par History
     223             : !>      01.2009 created
     224             : !> \author Teodoro Laino
     225             : ! **************************************************************************************************
     226       42545 :    SUBROUTINE metadyn_integrator(force_env, itimes, vel, rand)
     227             :       TYPE(force_env_type), POINTER            :: force_env
     228             :       INTEGER, INTENT(IN)                      :: itimes
     229             :       REAL(KIND=dp), DIMENSION(:, :), &
     230             :          INTENT(INOUT), OPTIONAL                :: vel
     231             :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, &
     232             :          POINTER                                :: rand
     233             : 
     234             :       CHARACTER(len=*), PARAMETER :: routineN = 'metadyn_integrator'
     235             : 
     236             :       INTEGER                                  :: handle, plumed_itimes
     237             : #if defined (__PLUMED2)
     238             :       INTEGER                                  :: i_part, natom_plumed
     239             :       TYPE(cell_type), POINTER                 :: cell
     240             :       TYPE(cp_subsys_type), POINTER            :: subsys
     241             : #endif
     242             : #if defined (__PLUMED2)
     243             :       TYPE(meta_env_type), POINTER             :: meta_env
     244       42545 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: mass_plumed
     245             :       REAL(KIND=dp), DIMENSION(3, 3)            :: plu_vir, celltbt
     246             :       REAL(KIND=dp)                            :: stpcfg
     247             :       REAL(KIND=dp), ALLOCATABLE, &
     248       42545 :          DIMENSION(:)                           :: pos_plumed_x, pos_plumed_y, pos_plumed_z
     249             :       REAL(KIND=dp), ALLOCATABLE, &
     250       42545 :          DIMENSION(:)                           :: force_plumed_x, force_plumed_y, force_plumed_z
     251             : #endif
     252             : 
     253       42545 :       CALL timeset(routineN, handle)
     254             : 
     255             :       ! Apply Metadynamics
     256       42545 :       IF (ASSOCIATED(force_env%meta_env)) THEN
     257       13694 :          IF (force_env%meta_env%use_plumed .EQV. .TRUE.) THEN
     258          10 :             plumed_itimes = itimes
     259             : #if defined (__PLUMED2)
     260          10 :             CALL force_env_get(force_env, meta_env=meta_env, subsys=subsys, cell=cell)
     261          10 :             natom_plumed = subsys%particles%n_els
     262          30 :             ALLOCATE (pos_plumed_x(natom_plumed))
     263          20 :             ALLOCATE (pos_plumed_y(natom_plumed))
     264          20 :             ALLOCATE (pos_plumed_z(natom_plumed))
     265             : 
     266          20 :             ALLOCATE (force_plumed_x(natom_plumed))
     267          20 :             ALLOCATE (force_plumed_y(natom_plumed))
     268          20 :             ALLOCATE (force_plumed_z(natom_plumed))
     269             : 
     270          20 :             ALLOCATE (mass_plumed(natom_plumed))
     271             : 
     272         100 :             force_plumed_x(:) = 0.0d0
     273         100 :             force_plumed_y(:) = 0.0d0
     274         100 :             force_plumed_z(:) = 0.0d0
     275             : 
     276         100 :             DO i_part = 1, natom_plumed
     277          90 :                pos_plumed_x(i_part) = subsys%particles%els(i_part)%r(1)
     278          90 :                pos_plumed_y(i_part) = subsys%particles%els(i_part)%r(2)
     279          90 :                pos_plumed_z(i_part) = subsys%particles%els(i_part)%r(3)
     280         100 :                mass_plumed(i_part) = subsys%particles%els(i_part)%atomic_kind%mass
     281             :             END DO
     282             : 
     283             :             ! stupid cell conversion, to be fixed
     284          10 :             celltbt(1, 1) = cell%hmat(1, 1)
     285          10 :             celltbt(1, 2) = cell%hmat(1, 2)
     286          10 :             celltbt(1, 3) = cell%hmat(1, 3)
     287          10 :             celltbt(2, 1) = cell%hmat(2, 1)
     288          10 :             celltbt(2, 2) = cell%hmat(2, 2)
     289          10 :             celltbt(2, 3) = cell%hmat(2, 3)
     290          10 :             celltbt(3, 1) = cell%hmat(3, 1)
     291          10 :             celltbt(3, 2) = cell%hmat(3, 2)
     292          10 :             celltbt(3, 3) = cell%hmat(3, 3)
     293             : 
     294             :             ! virial
     295          10 :             plu_vir(:, :) = 0.0d0
     296             : 
     297          10 :             CALL force_env_get(force_env, potential_energy=stpcfg)
     298             : 
     299          10 :             CALL plumed_gcmd_int("setStep"//CHAR(0), plumed_itimes)
     300          10 :             CALL plumed_gcmd_doubles("setPositionsX"//CHAR(0), pos_plumed_x(:))
     301          10 :             CALL plumed_gcmd_doubles("setPositionsY"//CHAR(0), pos_plumed_y(:))
     302          10 :             CALL plumed_gcmd_doubles("setPositionsZ"//CHAR(0), pos_plumed_z(:))
     303          10 :             CALL plumed_gcmd_doubles("setMasses"//CHAR(0), mass_plumed(:))
     304          10 :             CALL plumed_gcmd_doubles("setBox"//CHAR(0), celltbt)
     305          10 :             CALL plumed_gcmd_doubles("setVirial"//CHAR(0), plu_vir) ! PluMed Output, NOT ACTUALLY USED !
     306          10 :             CALL plumed_gcmd_double("setEnergy"//CHAR(0), stpcfg)
     307          10 :             CALL plumed_gcmd_doubles("setForcesX"//CHAR(0), force_plumed_x(:)) ! PluMed Output !
     308          10 :             CALL plumed_gcmd_doubles("setForcesY"//CHAR(0), force_plumed_y(:)) ! PluMed Output !
     309          10 :             CALL plumed_gcmd_doubles("setForcesZ"//CHAR(0), force_plumed_z(:)) ! PluMed Output !
     310             : 
     311          10 :             CALL plumed_gcmd_int("prepareCalc"//CHAR(0), 0)
     312          10 :             CALL plumed_gcmd_int("prepareDependencies"//CHAR(0), 0)
     313          10 :             CALL plumed_gcmd_int("shareData"//CHAR(0), 0)
     314             : 
     315          10 :             CALL plumed_gcmd_int("performCalc"//CHAR(0), 0)
     316             : 
     317         100 :             DO i_part = 1, natom_plumed
     318          90 :                subsys%particles%els(i_part)%f(1) = subsys%particles%els(i_part)%f(1) + force_plumed_x(i_part)
     319          90 :                subsys%particles%els(i_part)%f(2) = subsys%particles%els(i_part)%f(2) + force_plumed_y(i_part)
     320         100 :                subsys%particles%els(i_part)%f(3) = subsys%particles%els(i_part)%f(3) + force_plumed_z(i_part)
     321             :             END DO
     322             : 
     323          10 :             DEALLOCATE (pos_plumed_x, pos_plumed_y, pos_plumed_z)
     324          10 :             DEALLOCATE (force_plumed_x, force_plumed_y, force_plumed_z)
     325          10 :             DEALLOCATE (mass_plumed)
     326             : 
     327             :             ! Constraints ONLY of Fixed Atom type
     328          20 :             CALL fix_atom_control(force_env)
     329             : #endif
     330             : 
     331             : #if !defined (__PLUMED2)
     332             :             CALL cp_abort(__LOCATION__, &
     333             :                           "Requested to use plumed for metadynamics, but cp2k was"// &
     334             :                           " not compiled with plumed support.")
     335             : #endif
     336             : 
     337             :          ELSE
     338       13684 :             IF (force_env%meta_env%langevin) THEN
     339         240 :                IF (.NOT. PRESENT(rand)) THEN
     340           0 :                   CPABORT("Langevin on COLVAR not implemented for this MD ensemble!")
     341             :                END IF
     342             :                !    *** Velocity Verlet for Langevin S(t)->S(t+1)
     343         240 :                CALL metadyn_position_colvar(force_env)
     344             :                !    *** Forces from Vs and  S(X(t+1))
     345         240 :                CALL metadyn_forces(force_env)
     346             :                !    *** Velocity Verlet for Langeving *** v(t+1/2)--> v(t)
     347         240 :                CALL metadyn_velocities_colvar(force_env, rand)
     348             :             ELSE
     349       13568 :                CALL metadyn_forces(force_env, vel)
     350             :             END IF
     351             :             !    *** Write down COVAR informations
     352       13684 :             CALL metadyn_write_colvar(force_env)
     353             :          END IF
     354             :       END IF
     355             : 
     356       42545 :       CALL timestop(handle)
     357             : 
     358       42545 :    END SUBROUTINE metadyn_integrator
     359             : 
     360             : ! **************************************************************************************************
     361             : !> \brief add forces to the subsys due to the metadynamics run
     362             : !>      possibly modifies the velocites (if reflective walls are applied)
     363             : !> \param force_env ...
     364             : !> \param vel ...
     365             : !> \par History
     366             : !>      04.2004 created
     367             : ! **************************************************************************************************
     368       13826 :    SUBROUTINE metadyn_forces(force_env, vel)
     369             :       TYPE(force_env_type), POINTER                      :: force_env
     370             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT), &
     371             :          OPTIONAL                                        :: vel
     372             : 
     373             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'metadyn_forces'
     374             : 
     375             :       INTEGER                                            :: handle, i, i_c, icolvar, ii, iwall
     376             :       LOGICAL                                            :: explicit
     377             :       REAL(kind=dp)                                      :: check_val, diff_ss, dt, ekin_w, fac_t, &
     378             :                                                             fft, norm, rval, scal, scalf, &
     379             :                                                             ss0_test, tol_ekin
     380       13826 :       TYPE(colvar_p_type), DIMENSION(:), POINTER         :: colvar_p
     381             :       TYPE(cp_logger_type), POINTER                      :: logger
     382             :       TYPE(cp_subsys_type), POINTER                      :: subsys
     383             :       TYPE(meta_env_type), POINTER                       :: meta_env
     384             :       TYPE(metavar_type), POINTER                        :: cv
     385             :       TYPE(particle_list_type), POINTER                  :: particles
     386             :       TYPE(section_vals_type), POINTER                   :: ss0_section, vvp_section
     387             : 
     388       13826 :       NULLIFY (logger, meta_env)
     389       13826 :       meta_env => force_env%meta_env
     390           0 :       IF (.NOT. ASSOCIATED(meta_env)) RETURN
     391             : 
     392       13826 :       CALL timeset(routineN, handle)
     393       13826 :       logger => cp_get_default_logger()
     394       13826 :       NULLIFY (colvar_p, subsys, cv, ss0_section, vvp_section)
     395       13826 :       CALL force_env_get(force_env, subsys=subsys)
     396             : 
     397       13826 :       dt = meta_env%dt
     398       13826 :       IF (.NOT. meta_env%restart) meta_env%n_steps = meta_env%n_steps + 1
     399             : 
     400             :       ! Initialize velocity
     401       13826 :       IF (meta_env%restart .AND. meta_env%extended_lagrange) THEN
     402          54 :          meta_env%ekin_s = 0.0_dp
     403         130 :          DO i_c = 1, meta_env%n_colvar
     404          76 :             cv => meta_env%metavar(i_c)
     405          76 :             cv%vvp = force_env%globenv%gaussian_rng_stream%next()
     406         130 :             meta_env%ekin_s = meta_env%ekin_s + 0.5_dp*cv%mass*cv%vvp**2
     407             :          END DO
     408          54 :          ekin_w = 0.5_dp*meta_env%temp_wanted*REAL(meta_env%n_colvar, KIND=dp)
     409          54 :          fac_t = SQRT(ekin_w/MAX(meta_env%ekin_s, 1.0E-8_dp))
     410         130 :          DO i_c = 1, meta_env%n_colvar
     411          76 :             cv => meta_env%metavar(i_c)
     412         130 :             cv%vvp = cv%vvp*fac_t
     413             :          END DO
     414          54 :          meta_env%ekin_s = 0.0_dp
     415             :       END IF
     416             : 
     417             :       !    *** Velocity Verlet for Langevin S(t)->S(t+1)
     418             :       ! compute ss and the derivative of ss with respect to the atomic positions
     419       28396 :       DO i_c = 1, meta_env%n_colvar
     420       14570 :          cv => meta_env%metavar(i_c)
     421       14570 :          icolvar = cv%icolvar
     422       14570 :          CALL colvar_eval_glob_f(icolvar, force_env)
     423       14570 :          cv%ss = subsys%colvar_p(icolvar)%colvar%ss
     424             : 
     425             :          ! Setup the periodic flag if the COLVAR is (-pi,pi] periodic
     426       14570 :          cv%periodic = (subsys%colvar_p(icolvar)%colvar%type_id == torsion_colvar_id)
     427             : 
     428             :          ! Restart for Extended Lagrangian Metadynamics
     429       14570 :          IF (meta_env%restart) THEN
     430             :             ! Initialize the position of the collective variable in the extended lagrange
     431         188 :             ss0_section => section_vals_get_subs_vals(meta_env%metadyn_section, "EXT_LAGRANGE_SS0")
     432         188 :             CALL section_vals_get(ss0_section, explicit=explicit)
     433         188 :             IF (explicit) THEN
     434             :                CALL section_vals_val_get(ss0_section, "_DEFAULT_KEYWORD_", &
     435           4 :                                          i_rep_val=i_c, r_val=rval)
     436           4 :                cv%ss0 = rval
     437             :             ELSE
     438         184 :                cv%ss0 = cv%ss
     439             :             END IF
     440         188 :             vvp_section => section_vals_get_subs_vals(meta_env%metadyn_section, "EXT_LAGRANGE_VVP")
     441         188 :             CALL section_vals_get(vvp_section, explicit=explicit)
     442         188 :             IF (explicit) THEN
     443             :                CALL section_vals_val_get(vvp_section, "_DEFAULT_KEYWORD_", &
     444           4 :                                          i_rep_val=i_c, r_val=rval)
     445           4 :                cv%vvp = rval
     446             :             END IF
     447             :          END IF
     448             :          !
     449       28396 :          IF (.NOT. meta_env%extended_lagrange) THEN
     450       12404 :             cv%ss0 = cv%ss
     451       12404 :             cv%vvp = 0.0_dp
     452             :          END IF
     453             :       END DO
     454             :       ! History dependent forces (evaluated at s0)
     455       13826 :       IF (meta_env%do_hills) CALL hills(meta_env)
     456             : 
     457             :       ! Apply walls to the colvars
     458       13826 :       CALL meta_walls(meta_env)
     459             : 
     460       13826 :       meta_env%restart = .FALSE.
     461       13826 :       IF (.NOT. meta_env%extended_lagrange) THEN
     462       12210 :          meta_env%ekin_s = 0.0_dp
     463       12210 :          meta_env%epot_s = 0.0_dp
     464       12210 :          meta_env%epot_walls = 0.0_dp
     465       24614 :          DO i_c = 1, meta_env%n_colvar
     466       12404 :             cv => meta_env%metavar(i_c)
     467       12404 :             cv%epot_s = 0.0_dp
     468       12404 :             cv%ff_s = 0.0_dp
     469       12404 :             meta_env%epot_walls = meta_env%epot_walls + cv%epot_walls
     470       12404 :             icolvar = cv%icolvar
     471       12404 :             NULLIFY (particles)
     472             :             CALL cp_subsys_get(subsys, colvar_p=colvar_p, &
     473       12404 :                                particles=particles)
     474       62302 :             DO ii = 1, colvar_p(icolvar)%colvar%n_atom_s
     475       37688 :                i = colvar_p(icolvar)%colvar%i_atom(ii)
     476       37688 :                fft = cv%ff_hills + cv%ff_walls
     477      276220 :                particles%els(i)%f = particles%els(i)%f + fft*colvar_p(icolvar)%colvar%dsdr(:, ii)
     478             :             END DO
     479             :          END DO
     480             :       ELSE
     481        1616 :          meta_env%ekin_s = 0.0_dp
     482        1616 :          meta_env%epot_s = 0.0_dp
     483        1616 :          meta_env%epot_walls = 0.0_dp
     484        3782 :          DO i_c = 1, meta_env%n_colvar
     485        2166 :             cv => meta_env%metavar(i_c)
     486        2166 :             diff_ss = cv%ss - cv%ss0
     487        2166 :             IF (cv%periodic) THEN
     488             :                ! The difference of a periodic COLVAR is always within [-pi,pi]
     489           0 :                diff_ss = SIGN(1.0_dp, ASIN(SIN(diff_ss)))*ACOS(COS(diff_ss))
     490             :             END IF
     491        2166 :             cv%epot_s = 0.5_dp*cv%lambda*(diff_ss)**2.0_dp
     492        2166 :             cv%ff_s = cv%lambda*(diff_ss)
     493        2166 :             icolvar = cv%icolvar
     494             :             ! forces on the atoms
     495        2166 :             NULLIFY (particles)
     496             :             CALL cp_subsys_get(subsys, colvar_p=colvar_p, &
     497        2166 :                                particles=particles)
     498       10944 :             DO ii = 1, colvar_p(icolvar)%colvar%n_atom_s
     499        8778 :                i = colvar_p(icolvar)%colvar%i_atom(ii)
     500       63612 :                particles%els(i)%f = particles%els(i)%f - cv%ff_s*colvar_p(icolvar)%colvar%dsdr(:, ii)
     501             :             END DO
     502             :             !  velocity verlet on the s0 if NOT langevin
     503        3782 :             IF (.NOT. meta_env%langevin) THEN
     504        1678 :                fft = cv%ff_s + cv%ff_hills + cv%ff_walls
     505        1678 :                cv%vvp = cv%vvp + dt*fft/cv%mass
     506        1678 :                meta_env%ekin_s = meta_env%ekin_s + 0.5_dp*cv%mass*cv%vvp**2
     507        1678 :                meta_env%epot_s = meta_env%epot_s + cv%epot_s
     508        1678 :                meta_env%epot_walls = meta_env%epot_walls + cv%epot_walls
     509             :             END IF
     510             :          END DO
     511             :          !  velocity rescaling on the s0
     512        1616 :          IF (meta_env%tempcontrol .AND. (.NOT. meta_env%langevin)) THEN
     513         604 :             ekin_w = 0.5_dp*meta_env%temp_wanted*REAL(meta_env%n_colvar, KIND=dp)
     514         604 :             tol_ekin = 0.5_dp*meta_env%toll_temp*REAL(meta_env%n_colvar, KIND=dp)
     515         604 :             IF (ABS(ekin_w - meta_env%ekin_s) > tol_ekin) THEN
     516         354 :                fac_t = SQRT(ekin_w/MAX(meta_env%ekin_s, 1.0E-8_dp))
     517         772 :                DO i_c = 1, meta_env%n_colvar
     518         418 :                   cv => meta_env%metavar(i_c)
     519         772 :                   cv%vvp = cv%vvp*fac_t
     520             :                END DO
     521         354 :                meta_env%ekin_s = ekin_w
     522             :             END IF
     523             :          END IF
     524             :          ! Reflective Wall only for s0
     525        3782 :          DO i_c = 1, meta_env%n_colvar
     526        2166 :             cv => meta_env%metavar(i_c)
     527        3782 :             IF (cv%do_wall) THEN
     528         700 :                DO iwall = 1, SIZE(cv%walls)
     529         248 :                   SELECT CASE (cv%walls(iwall)%id_type)
     530             :                   CASE (do_wall_reflective)
     531         204 :                      ss0_test = cv%ss0 + dt*cv%vvp
     532         204 :                      IF (cv%periodic) THEN
     533             :                         ! A periodic COLVAR is always within [-pi,pi]
     534           0 :                         ss0_test = SIGN(1.0_dp, ASIN(SIN(ss0_test)))*ACOS(COS(ss0_test))
     535             :                      END IF
     536         656 :                      SELECT CASE (cv%walls(iwall)%id_direction)
     537             :                      CASE (do_wall_p)
     538         102 :                         IF ((ss0_test > cv%walls(iwall)%pos) .AND. (cv%vvp > 0)) cv%vvp = -cv%vvp
     539             :                      CASE (do_wall_m)
     540         102 :                         IF ((ss0_test < cv%walls(iwall)%pos) .AND. (cv%vvp < 0)) cv%vvp = -cv%vvp
     541             :                      END SELECT
     542             :                   END SELECT
     543             :                END DO
     544             :             END IF
     545             :          END DO
     546             :          ! Update of ss0 if NOT langevin
     547        1616 :          IF (.NOT. meta_env%langevin) THEN
     548        3050 :             DO i_c = 1, meta_env%n_colvar
     549        1678 :                cv => meta_env%metavar(i_c)
     550        1678 :                cv%ss0 = cv%ss0 + dt*cv%vvp
     551        3050 :                IF (cv%periodic) THEN
     552             :                   ! A periodic COLVAR is always within [-pi,pi]
     553           0 :                   cv%ss0 = SIGN(1.0_dp, ASIN(SIN(cv%ss0)))*ACOS(COS(cv%ss0))
     554             :                END IF
     555             :             END DO
     556             :          END IF
     557             :       END IF
     558             :       ! Constraints ONLY of Fixed Atom type
     559       13826 :       CALL fix_atom_control(force_env)
     560             : 
     561             :       ! Reflective Wall only for ss
     562       28396 :       DO i_c = 1, meta_env%n_colvar
     563       14570 :          cv => meta_env%metavar(i_c)
     564       28396 :          IF (cv%do_wall) THEN
     565       23162 :             DO iwall = 1, SIZE(cv%walls)
     566       11276 :                SELECT CASE (cv%walls(iwall)%id_type)
     567             :                CASE (do_wall_reflective)
     568         408 :                   SELECT CASE (cv%walls(iwall)%id_direction)
     569             :                   CASE (do_wall_p)
     570         204 :                      IF (cv%ss < cv%walls(iwall)%pos) CYCLE
     571         204 :                      check_val = -1.0_dp
     572             :                   CASE (do_wall_m)
     573         204 :                      IF (cv%ss > cv%walls(iwall)%pos) CYCLE
     574             :                      check_val = 1.0_dp
     575             :                   END SELECT
     576           2 :                   NULLIFY (particles)
     577           2 :                   icolvar = cv%icolvar
     578           2 :                   CALL cp_subsys_get(subsys, colvar_p=colvar_p, particles=particles)
     579           2 :                   scal = 0.0_dp
     580           2 :                   scalf = 0.0_dp
     581           2 :                   norm = 0.0_dp
     582          10 :                   DO ii = 1, colvar_p(icolvar)%colvar%n_atom_s
     583           8 :                      i = colvar_p(icolvar)%colvar%i_atom(ii)
     584           8 :                      IF (PRESENT(vel)) THEN
     585           8 :                         scal = scal + vel(1, i)*colvar_p(icolvar)%colvar%dsdr(1, ii)
     586           8 :                         scal = scal + vel(2, i)*colvar_p(icolvar)%colvar%dsdr(2, ii)
     587           8 :                         scal = scal + vel(3, i)*colvar_p(icolvar)%colvar%dsdr(3, ii)
     588             :                      ELSE
     589           0 :                         scal = scal + particles%els(i)%v(1)*colvar_p(icolvar)%colvar%dsdr(1, ii)
     590           0 :                         scal = scal + particles%els(i)%v(2)*colvar_p(icolvar)%colvar%dsdr(2, ii)
     591           0 :                         scal = scal + particles%els(i)%v(3)*colvar_p(icolvar)%colvar%dsdr(3, ii)
     592             :                      END IF
     593           8 :                      scalf = scalf + particles%els(i)%f(1)*colvar_p(icolvar)%colvar%dsdr(1, ii)
     594           8 :                      scalf = scalf + particles%els(i)%f(2)*colvar_p(icolvar)%colvar%dsdr(2, ii)
     595           8 :                      scalf = scalf + particles%els(i)%f(3)*colvar_p(icolvar)%colvar%dsdr(3, ii)
     596           8 :                      norm = norm + colvar_p(icolvar)%colvar%dsdr(1, ii)**2
     597           8 :                      norm = norm + colvar_p(icolvar)%colvar%dsdr(2, ii)**2
     598          10 :                      norm = norm + colvar_p(icolvar)%colvar%dsdr(3, ii)**2
     599             :                   END DO
     600           2 :                   IF (norm /= 0.0_dp) scal = scal/norm
     601           2 :                   IF (norm /= 0.0_dp) scalf = scalf/norm
     602             : 
     603           2 :                   IF (scal*check_val > 0.0_dp) CYCLE
     604       11896 :                   DO ii = 1, colvar_p(icolvar)%colvar%n_atom_s
     605           8 :                      i = colvar_p(icolvar)%colvar%i_atom(ii)
     606           8 :                      IF (PRESENT(vel)) THEN
     607          32 :                         vel(:, i) = vel(:, i) - 2.0_dp*colvar_p(icolvar)%colvar%dsdr(:, ii)*scal
     608             :                      ELSE
     609           0 :                         particles%els(i)%v(:) = particles%els(i)%v(:) - 2.0_dp*colvar_p(icolvar)%colvar%dsdr(:, ii)*scal
     610             :                      END IF
     611             :                      ! Nullify forces along the colvar (this avoids the weird behaviors of the reflective wall)
     612          58 :                      particles%els(i)%f(:) = particles%els(i)%f(:) - colvar_p(icolvar)%colvar%dsdr(:, ii)*scalf
     613             :                   END DO
     614             :                END SELECT
     615             :             END DO
     616             :          END IF
     617             :       END DO
     618             : 
     619       13826 :       CALL timestop(handle)
     620       13826 :    END SUBROUTINE metadyn_forces
     621             : 
     622             : ! **************************************************************************************************
     623             : !> \brief Evolves velocities COLVAR according to
     624             : !>        Vanden-Eijnden Ciccotti C.Phys.Letter 429 (2006) 310-316
     625             : !> \param force_env ...
     626             : !> \param rand ...
     627             : !> \date  01.2009
     628             : !> \author Fabio Sterpone and Teodoro Laino
     629             : ! **************************************************************************************************
     630         480 :    SUBROUTINE metadyn_velocities_colvar(force_env, rand)
     631             :       TYPE(force_env_type), POINTER                      :: force_env
     632             :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT), &
     633             :          OPTIONAL                                        :: rand
     634             : 
     635             :       CHARACTER(len=*), PARAMETER :: routineN = 'metadyn_velocities_colvar'
     636             : 
     637             :       INTEGER                                            :: handle, i_c
     638             :       REAL(kind=dp)                                      :: diff_ss, dt, fft, sigma
     639             :       TYPE(cp_logger_type), POINTER                      :: logger
     640             :       TYPE(meta_env_type), POINTER                       :: meta_env
     641             :       TYPE(metavar_type), POINTER                        :: cv
     642             : 
     643         480 :       NULLIFY (logger, meta_env, cv)
     644         480 :       meta_env => force_env%meta_env
     645         480 :       IF (.NOT. ASSOCIATED(meta_env)) RETURN
     646             : 
     647         480 :       CALL timeset(routineN, handle)
     648         480 :       logger => cp_get_default_logger()
     649             :       ! Add citation
     650         480 :       IF (meta_env%langevin) CALL cite_reference(VandenCic2006)
     651             : 
     652         480 :       dt = meta_env%dt
     653             :       ! History dependent forces (evaluated at s0)
     654         480 :       IF (meta_env%do_hills) CALL hills(meta_env)
     655             : 
     656             :       ! Evolve Velocities
     657         480 :       meta_env%ekin_s = 0.0_dp
     658         480 :       meta_env%epot_walls = 0.0_dp
     659        1440 :       DO i_c = 1, meta_env%n_colvar
     660         960 :          cv => meta_env%metavar(i_c)
     661         960 :          diff_ss = cv%ss - cv%ss0
     662         960 :          IF (cv%periodic) THEN
     663             :             ! The difference of a periodic COLVAR is always within [-pi,pi]
     664           0 :             diff_ss = SIGN(1.0_dp, ASIN(SIN(diff_ss)))*ACOS(COS(diff_ss))
     665             :          END IF
     666         960 :          cv%epot_s = 0.5_dp*cv%lambda*(diff_ss)**2.0_dp
     667         960 :          cv%ff_s = cv%lambda*(diff_ss)
     668             : 
     669         960 :          fft = cv%ff_s + cv%ff_hills
     670         960 :          sigma = SQRT((meta_env%temp_wanted*kelvin)*2.0_dp*(boltzmann/joule)*cv%gamma/cv%mass)
     671             :          cv%vvp = cv%vvp + 0.5_dp*dt*fft/cv%mass - 0.5_dp*dt*cv%gamma*cv%vvp + &
     672         960 :                   0.5_dp*SQRT(dt)*sigma*rand(i_c)
     673         960 :          meta_env%ekin_s = meta_env%ekin_s + 0.5_dp*cv%mass*cv%vvp**2
     674        1440 :          meta_env%epot_walls = meta_env%epot_walls + cv%epot_walls
     675             :       END DO
     676         480 :       CALL timestop(handle)
     677             : 
     678             :    END SUBROUTINE metadyn_velocities_colvar
     679             : 
     680             : ! **************************************************************************************************
     681             : !> \brief Evolves COLVAR position
     682             : !>        Vanden-Eijnden Ciccotti C.Phys.Letter 429 (2006) 310-316
     683             : !> \param force_env ...
     684             : !> \date  01.2009
     685             : !> \author Fabio Sterpone and Teodoro Laino
     686             : ! **************************************************************************************************
     687         480 :    SUBROUTINE metadyn_position_colvar(force_env)
     688             :       TYPE(force_env_type), POINTER                      :: force_env
     689             : 
     690             :       CHARACTER(len=*), PARAMETER :: routineN = 'metadyn_position_colvar'
     691             : 
     692             :       INTEGER                                            :: handle, i_c
     693             :       REAL(kind=dp)                                      :: dt
     694             :       TYPE(cp_logger_type), POINTER                      :: logger
     695             :       TYPE(meta_env_type), POINTER                       :: meta_env
     696             :       TYPE(metavar_type), POINTER                        :: cv
     697             : 
     698         240 :       NULLIFY (logger, meta_env, cv)
     699         240 :       meta_env => force_env%meta_env
     700         240 :       IF (.NOT. ASSOCIATED(meta_env)) RETURN
     701             : 
     702         240 :       CALL timeset(routineN, handle)
     703         240 :       logger => cp_get_default_logger()
     704             : 
     705             :       ! Add citation
     706         240 :       IF (meta_env%langevin) CALL cite_reference(VandenCic2006)
     707         240 :       dt = meta_env%dt
     708             : 
     709             :       ! Update of ss0
     710         720 :       DO i_c = 1, meta_env%n_colvar
     711         480 :          cv => meta_env%metavar(i_c)
     712         480 :          cv%ss0 = cv%ss0 + dt*cv%vvp
     713         720 :          IF (cv%periodic) THEN
     714             :             ! A periodic COLVAR is always within [-pi,pi]
     715           0 :             cv%ss0 = SIGN(1.0_dp, ASIN(SIN(cv%ss0)))*ACOS(COS(cv%ss0))
     716             :          END IF
     717             :       END DO
     718         240 :       CALL timestop(handle)
     719             : 
     720             :    END SUBROUTINE metadyn_position_colvar
     721             : 
     722             : ! **************************************************************************************************
     723             : !> \brief Write down COLVAR information evolved  according to
     724             : !>        Vanden-Eijnden Ciccotti C.Phys.Letter 429 (2006) 310-316
     725             : !> \param force_env ...
     726             : !> \date  01.2009
     727             : !> \author Fabio Sterpone and Teodoro Laino
     728             : ! **************************************************************************************************
     729       27652 :    SUBROUTINE metadyn_write_colvar(force_env)
     730             :       TYPE(force_env_type), POINTER                      :: force_env
     731             : 
     732             :       CHARACTER(len=*), PARAMETER :: routineN = 'metadyn_write_colvar'
     733             : 
     734             :       INTEGER                                            :: handle, i, i_c, iw
     735             :       REAL(KIND=dp)                                      :: diff_ss, temp
     736             :       TYPE(cp_logger_type), POINTER                      :: logger
     737             :       TYPE(meta_env_type), POINTER                       :: meta_env
     738             :       TYPE(metavar_type), POINTER                        :: cv
     739             : 
     740       13826 :       NULLIFY (logger, meta_env, cv)
     741       13826 :       meta_env => force_env%meta_env
     742       13826 :       IF (.NOT. ASSOCIATED(meta_env)) RETURN
     743             : 
     744       13826 :       CALL timeset(routineN, handle)
     745       13826 :       logger => cp_get_default_logger()
     746             : 
     747             :       ! If Langevin we need to recompute few quantities
     748             :       ! This does not apply to the standard lagrangian scheme since it is
     749             :       ! implemented with a plain Newton integration scheme.. while Langevin
     750             :       ! follows the correct Verlet integration.. This will have to be made
     751             :       ! uniform in the future (Teodoro Laino - 01.2009)
     752       13826 :       IF (meta_env%langevin) THEN
     753         244 :          meta_env%ekin_s = 0.0_dp
     754         244 :          meta_env%epot_s = 0.0_dp
     755         732 :          DO i_c = 1, meta_env%n_colvar
     756         488 :             cv => meta_env%metavar(i_c)
     757         488 :             diff_ss = cv%ss - cv%ss0
     758         488 :             IF (cv%periodic) THEN
     759             :                ! The difference of a periodic COLVAR is always within [-pi,pi]
     760           0 :                diff_ss = SIGN(1.0_dp, ASIN(SIN(diff_ss)))*ACOS(COS(diff_ss))
     761             :             END IF
     762         488 :             cv%epot_s = 0.5_dp*cv%lambda*(diff_ss)**2.0_dp
     763         488 :             cv%ff_s = cv%lambda*(diff_ss)
     764             : 
     765         488 :             meta_env%epot_s = meta_env%epot_s + cv%epot_s
     766         732 :             meta_env%ekin_s = meta_env%ekin_s + 0.5_dp*cv%mass*cv%vvp**2
     767             :          END DO
     768             :       END IF
     769             : 
     770             :       ! write COLVAR file
     771             :       iw = cp_print_key_unit_nr(logger, meta_env%metadyn_section, &
     772       13826 :                                 "PRINT%COLVAR", extension=".metadynLog")
     773       13826 :       IF (iw > 0) THEN
     774        6631 :          IF (meta_env%extended_lagrange) THEN
     775         781 :             WRITE (iw, '(f16.8,70f15.8)') meta_env%time*femtoseconds, &
     776        2591 :                (meta_env%metavar(i)%ss0, i=1, meta_env%n_colvar), &
     777        2591 :                (meta_env%metavar(i)%ss, i=1, meta_env%n_colvar), &
     778        2591 :                (meta_env%metavar(i)%ff_s, i=1, meta_env%n_colvar), &
     779        2591 :                (meta_env%metavar(i)%ff_hills, i=1, meta_env%n_colvar), &
     780        2591 :                (meta_env%metavar(i)%ff_walls, i=1, meta_env%n_colvar), &
     781        2591 :                (meta_env%metavar(i)%vvp, i=1, meta_env%n_colvar), &
     782         781 :                meta_env%epot_s, &
     783         781 :                meta_env%hills_env%energy, &
     784         781 :                meta_env%epot_walls, &
     785       12422 :                (meta_env%ekin_s)*2.0_dp/(REAL(meta_env%n_colvar, KIND=dp))*kelvin
     786             :          ELSE
     787        5850 :             WRITE (iw, '(f16.8,40f13.5)') meta_env%time*femtoseconds, &
     788       17647 :                (meta_env%metavar(i)%ss0, i=1, meta_env%n_colvar), &
     789       17647 :                (meta_env%metavar(i)%ff_hills, i=1, meta_env%n_colvar), &
     790       17647 :                (meta_env%metavar(i)%ff_walls, i=1, meta_env%n_colvar), &
     791        5850 :                meta_env%hills_env%energy, &
     792       47091 :                meta_env%epot_walls
     793             :          END IF
     794             :       END IF
     795             :       CALL cp_print_key_finished_output(iw, logger, meta_env%metadyn_section, &
     796       13826 :                                         "PRINT%COLVAR")
     797             : 
     798             :       ! Temperature for COLVAR
     799       13826 :       IF (meta_env%extended_lagrange) THEN
     800        1616 :          temp = meta_env%ekin_s*2.0_dp/(REAL(meta_env%n_colvar, KIND=dp))*kelvin
     801             :          meta_env%avg_temp = (meta_env%avg_temp*REAL(meta_env%n_steps, KIND=dp) + &
     802        1616 :                               temp)/REAL(meta_env%n_steps + 1, KIND=dp)
     803             :          iw = cp_print_key_unit_nr(logger, meta_env%metadyn_section, &
     804        1616 :                                    "PRINT%TEMPERATURE_COLVAR", extension=".metadynLog")
     805        1616 :          IF (iw > 0) THEN
     806         808 :             WRITE (iw, '(T2,79("-"))')
     807         808 :             WRITE (iw, '( A,T51,f10.2,T71,f10.2)') ' COLVARS INSTANTANEOUS/AVERAGE TEMPERATURE ', &
     808        1616 :                temp, meta_env%avg_temp
     809         808 :             WRITE (iw, '(T2,79("-"))')
     810             :          END IF
     811             :          CALL cp_print_key_finished_output(iw, logger, meta_env%metadyn_section, &
     812        1616 :                                            "PRINT%TEMPERATURE_COLVAR")
     813             :       END IF
     814       13826 :       CALL timestop(handle)
     815             : 
     816             :    END SUBROUTINE metadyn_write_colvar
     817             : 
     818             : ! **************************************************************************************************
     819             : !> \brief Major driver for adding hills and computing forces due to the history
     820             : !>        dependent term
     821             : !> \param meta_env ...
     822             : !> \par History
     823             : !>      04.2004 created
     824             : !>      10.2008 Teodoro Laino [tlaino] - University of Zurich
     825             : !>              Major rewriting and addition of multiple walkers
     826             : ! **************************************************************************************************
     827       11278 :    SUBROUTINE hills(meta_env)
     828             :       TYPE(meta_env_type), POINTER                       :: meta_env
     829             : 
     830             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'hills'
     831             : 
     832             :       INTEGER                                            :: handle, i, i_hills, ih, intermeta_steps, &
     833             :                                                             iter_nr, iw, n_colvar, n_hills_start, &
     834             :                                                             n_step
     835             :       LOGICAL                                            :: force_gauss
     836             :       REAL(KIND=dp)                                      :: cut_func, dfunc, diff, dp2, frac, &
     837             :                                                             slow_growth, V_now_here, V_to_fes, &
     838             :                                                             wtww, ww
     839       11278 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: ddp, denf, diff_ss, local_last_hills, &
     840       11278 :                                                             numf
     841             :       TYPE(cp_logger_type), POINTER                      :: logger
     842             :       TYPE(hills_env_type), POINTER                      :: hills_env
     843       11278 :       TYPE(metavar_type), DIMENSION(:), POINTER          :: colvars
     844             :       TYPE(multiple_walkers_type), POINTER               :: multiple_walkers
     845             : 
     846       11278 :       CALL timeset(routineN, handle)
     847             : 
     848       11278 :       NULLIFY (hills_env, multiple_walkers, logger, colvars, ddp, local_last_hills)
     849       11278 :       hills_env => meta_env%hills_env
     850       11278 :       logger => cp_get_default_logger()
     851       11278 :       colvars => meta_env%metavar
     852       11278 :       n_colvar = meta_env%n_colvar
     853       11278 :       n_step = meta_env%n_steps
     854             : 
     855             :       ! Create a temporary logger level specific for metadynamics
     856       11278 :       CALL cp_add_iter_level(logger%iter_info, "METADYNAMICS")
     857       11278 :       CALL get_meta_iter_level(meta_env, iter_nr)
     858       11278 :       CALL cp_iterate(logger%iter_info, last=.FALSE., iter_nr=iter_nr)
     859             : 
     860             :       ! Set-up restart if any
     861       11278 :       IF (meta_env%hills_env%restart) THEN
     862         118 :          meta_env%hills_env%restart = .FALSE.
     863         118 :          IF (meta_env%well_tempered) THEN
     864             :             CALL restart_hills(hills_env%ss_history, hills_env%delta_s_history, hills_env%ww_history, &
     865             :                                hills_env%ww, hills_env%n_hills, n_colvar, colvars, meta_env%metadyn_section, &
     866           2 :                                invdt_history=hills_env%invdt_history)
     867             :          ELSE
     868             :             CALL restart_hills(hills_env%ss_history, hills_env%delta_s_history, hills_env%ww_history, &
     869         116 :                                hills_env%ww, hills_env%n_hills, n_colvar, colvars, meta_env%metadyn_section)
     870             :          END IF
     871             :       END IF
     872             : 
     873             :       ! Proceed with normal calculation
     874       11278 :       intermeta_steps = n_step - hills_env%old_hill_step
     875       11278 :       force_gauss = .FALSE.
     876       11278 :       IF ((hills_env%min_disp > 0.0_dp) .AND. (hills_env%old_hill_number > 0) .AND. &
     877             :           (intermeta_steps >= hills_env%min_nt_hills)) THEN
     878         132 :          ALLOCATE (ddp(meta_env%n_colvar))
     879          88 :          ALLOCATE (local_last_hills(meta_env%n_colvar))
     880             : 
     881         220 :          local_last_hills(1:n_colvar) = hills_env%ss_history(1:n_colvar, hills_env%old_hill_number)
     882             : 
     883             :          !RG Calculate the displacement
     884          44 :          dp2 = 0.0_dp
     885         132 :          DO i = 1, n_colvar
     886          88 :             ddp(i) = colvars(i)%ss0 - local_last_hills(i)
     887          88 :             IF (colvars(i)%periodic) THEN
     888             :                ! The difference of a periodic COLVAR is always within [-pi,pi]
     889           0 :                ddp(i) = SIGN(1.0_dp, ASIN(SIN(ddp(i))))*ACOS(COS(ddp(i)))
     890             :             END IF
     891         132 :             dp2 = dp2 + ddp(i)**2
     892             :          END DO
     893          44 :          dp2 = SQRT(dp2)
     894          44 :          IF (dp2 > hills_env%min_disp) THEN
     895          16 :             force_gauss = .TRUE.
     896             :             iw = cp_print_key_unit_nr(logger, meta_env%metadyn_section, &
     897          16 :                                       "PRINT%PROGRAM_RUN_INFO", extension=".metadynLog")
     898          16 :             IF (iw > 0) THEN
     899             :                WRITE (UNIT=iw, FMT="(A,F0.6,A,F0.6)") &
     900           8 :                   " METADYN| Threshold value for COLVAR displacement exceeded: ", &
     901          16 :                   dp2, " > ", hills_env%min_disp
     902             :             END IF
     903             :             CALL cp_print_key_finished_output(iw, logger, meta_env%metadyn_section, &
     904          16 :                                               "PRINT%PROGRAM_RUN_INFO")
     905             :          END IF
     906          44 :          DEALLOCATE (ddp)
     907          44 :          DEALLOCATE (local_last_hills)
     908             :       END IF
     909             : 
     910             :       !RG keep into account adaptive hills
     911             :       IF (((MODULO(intermeta_steps, hills_env%nt_hills) == 0) .OR. force_gauss) &
     912       11278 :           .AND. (.NOT. meta_env%restart) .AND. (hills_env%nt_hills > 0)) THEN
     913        1116 :          IF (meta_env%do_multiple_walkers) multiple_walkers => meta_env%multiple_walkers
     914             : 
     915        1116 :          n_hills_start = hills_env%n_hills
     916             :          ! Add the hill corresponding to this location
     917        1116 :          IF (meta_env%well_tempered) THEN
     918             :             ! Well-Tempered scaling of hills height
     919             :             V_now_here = 0._dp
     920           6 :             DO ih = 1, hills_env%n_hills
     921           2 :                dp2 = 0._dp
     922           4 :                DO i = 1, n_colvar
     923           2 :                   diff = colvars(i)%ss0 - hills_env%ss_history(i, ih)
     924           2 :                   IF (colvars(i)%periodic) THEN
     925             :                      ! The difference of a periodic COLVAR is always within [-pi,pi]
     926           0 :                      diff = SIGN(1.0_dp, ASIN(SIN(diff)))*ACOS(COS(diff))
     927             :                   END IF
     928           2 :                   diff = (diff)/hills_env%delta_s_history(i, ih)
     929           4 :                   dp2 = dp2 + diff**2
     930             :                END DO
     931           2 :                V_to_fes = 1.0_dp + meta_env%wttemperature*hills_env%invdt_history(ih)
     932           6 :                V_now_here = V_now_here + hills_env%ww_history(ih)/V_to_fes*EXP(-0.5_dp*dp2)
     933             :             END DO
     934           4 :             wtww = hills_env%ww*EXP(-V_now_here*meta_env%invdt)
     935           4 :             ww = wtww*(1.0_dp + meta_env%wttemperature*meta_env%invdt)
     936           4 :             CALL add_hill_single(hills_env, colvars, ww, hills_env%n_hills, n_colvar, meta_env%invdt)
     937             :          ELSE
     938        1112 :             CALL add_hill_single(hills_env, colvars, hills_env%ww, hills_env%n_hills, n_colvar)
     939             :          END IF
     940             :          ! Update local n_hills counter
     941        1116 :          IF (meta_env%do_multiple_walkers) multiple_walkers%n_hills_local = multiple_walkers%n_hills_local + 1
     942             : 
     943        1116 :          hills_env%old_hill_number = hills_env%n_hills
     944        1116 :          hills_env%old_hill_step = n_step
     945             : 
     946             :          ! Update iteration level for printing
     947        1116 :          CALL get_meta_iter_level(meta_env, iter_nr)
     948        1116 :          CALL cp_iterate(logger%iter_info, last=.FALSE., iter_nr=iter_nr)
     949             : 
     950             :          ! Print just program_run_info
     951             :          iw = cp_print_key_unit_nr(logger, meta_env%metadyn_section, &
     952        1116 :                                    "PRINT%PROGRAM_RUN_INFO", extension=".metadynLog")
     953        1116 :          IF (iw > 0) THEN
     954         558 :             IF (meta_env%do_multiple_walkers) THEN
     955             :                WRITE (iw, '(/,1X,"METADYN|",A,I0,A,I0,A,/)') &
     956          66 :                   ' Global/Local Hills number (', hills_env%n_hills, '/', multiple_walkers%n_hills_local, &
     957         132 :                   ') added.'
     958             :             ELSE
     959         492 :                WRITE (iw, '(/,1X,"METADYN|",A,I0,A,/)') ' Hills number (', hills_env%n_hills, ') added.'
     960             :             END IF
     961             :          END IF
     962             :          CALL cp_print_key_finished_output(iw, logger, meta_env%metadyn_section, &
     963        1116 :                                            "PRINT%PROGRAM_RUN_INFO")
     964             : 
     965             :          ! Handle Multiple Walkers
     966        1116 :          IF (meta_env%do_multiple_walkers) THEN
     967             :             ! Print Local Hills file if requested
     968             :             iw = cp_print_key_unit_nr(logger, meta_env%metadyn_section, &
     969         132 :                                       "PRINT%HILLS", middle_name="LOCAL", extension=".metadynLog")
     970         132 :             IF (iw > 0) THEN
     971          66 :                WRITE (iw, '(f12.1,30f13.5)') meta_env%time*femtoseconds, &
     972         198 :                   (hills_env%ss_history(ih, hills_env%n_hills), ih=1, n_colvar), &
     973         132 :                   (hills_env%delta_s_history(ih, hills_env%n_hills), ih=1, n_colvar), &
     974         396 :                   hills_env%ww_history(hills_env%n_hills)
     975             :             END IF
     976             :             CALL cp_print_key_finished_output(iw, logger, meta_env%metadyn_section, &
     977         132 :                                               "PRINT%HILLS")
     978             : 
     979             :             ! Check the communication buffer of the other walkers
     980             :             CALL synchronize_multiple_walkers(multiple_walkers, hills_env, colvars, &
     981         132 :                                               n_colvar, meta_env%metadyn_section)
     982             :          END IF
     983             : 
     984             :          ! Print Hills file if requested (for multiple walkers this file includes
     985             :          ! the Hills coming from all the walkers).
     986             :          iw = cp_print_key_unit_nr(logger, meta_env%metadyn_section, &
     987        1116 :                                    "PRINT%HILLS", extension=".metadynLog")
     988        1116 :          IF (iw > 0) THEN
     989         697 :             DO i_hills = n_hills_start + 1, hills_env%n_hills
     990         373 :                WRITE (iw, '(f12.1,30f13.5)') meta_env%time*femtoseconds, &
     991        1182 :                   (hills_env%ss_history(ih, i_hills), ih=1, n_colvar), &
     992         809 :                   (hills_env%delta_s_history(ih, i_hills), ih=1, n_colvar), &
     993        2688 :                   hills_env%ww_history(i_hills)
     994             :             END DO
     995             :          END IF
     996             :          CALL cp_print_key_finished_output(iw, logger, meta_env%metadyn_section, &
     997        1116 :                                            "PRINT%HILLS")
     998             :       END IF
     999             : 
    1000             :       ! Computes forces due to the hills: history dependent term
    1001       33834 :       ALLOCATE (ddp(meta_env%n_colvar))
    1002       22556 :       ALLOCATE (diff_ss(meta_env%n_colvar))
    1003       22556 :       ALLOCATE (numf(meta_env%n_colvar))
    1004       22556 :       ALLOCATE (denf(meta_env%n_colvar))
    1005             : 
    1006       11278 :       hills_env%energy = 0.0_dp
    1007       23594 :       DO ih = 1, n_colvar
    1008       23594 :          colvars(ih)%ff_hills = 0.0_dp
    1009             :       END DO
    1010      123556 :       DO ih = 1, hills_env%n_hills
    1011      112278 :          slow_growth = 1.0_dp
    1012      112278 :          IF (hills_env%slow_growth .AND. (ih == hills_env%n_hills)) THEN
    1013        3804 :             slow_growth = REAL(n_step - hills_env%old_hill_step, dp)/REAL(hills_env%nt_hills, dp)
    1014             :          END IF
    1015      112278 :          dp2 = 0._dp
    1016      112278 :          cut_func = 1.0_dp
    1017      236078 :          DO i = 1, n_colvar
    1018      123800 :             diff_ss(i) = colvars(i)%ss0 - hills_env%ss_history(i, ih)
    1019      123800 :             IF (colvars(i)%periodic) THEN
    1020             :                ! The difference of a periodic COLVAR is always within [-pi,pi]
    1021           0 :                diff_ss(i) = SIGN(1.0_dp, ASIN(SIN(diff_ss(i))))*ACOS(COS(diff_ss(i)))
    1022             :             END IF
    1023      123800 :             IF (hills_env%delta_s_history(i, ih) == 0.0_dp) THEN
    1024             :                ! trick: scale = 0 is interpreted as infinitely wide Gaussian hill
    1025             :                ! instead of infinitely narrow. This way one can combine several
    1026             :                ! one-dimensional bias potentials in a multi-dimensional metadyn
    1027             :                ! simulation.
    1028           0 :                ddp(i) = 0.0_dp
    1029             :             ELSE
    1030      123800 :                ddp(i) = (diff_ss(i))/hills_env%delta_s_history(i, ih)
    1031             :             END IF
    1032      123800 :             dp2 = dp2 + ddp(i)**2
    1033      236078 :             IF (hills_env%tail_cutoff > 0.0_dp) THEN
    1034       38104 :                frac = ABS(ddp(i))/hills_env%tail_cutoff
    1035       38104 :                numf(i) = frac**hills_env%p_exp
    1036       38104 :                denf(i) = frac**hills_env%q_exp
    1037       38104 :                cut_func = cut_func*(1.0_dp - numf(i))/(1.0_dp - denf(i))
    1038             :             END IF
    1039             :          END DO
    1040             :          ! ff_hills contains the "force" due to the hills
    1041      112278 :          dfunc = hills_env%ww_history(ih)*EXP(-0.5_dp*dp2)*slow_growth
    1042      112278 :          IF (meta_env%well_tempered) dfunc = dfunc/(1.0_dp + meta_env%wttemperature*hills_env%invdt_history(ih))
    1043      112278 :          hills_env%energy = hills_env%energy + dfunc*cut_func
    1044      247356 :          DO i = 1, n_colvar
    1045      236078 :             IF (hills_env%delta_s_history(i, ih) /= 0.0_dp) THEN
    1046             :                ! only apply a force when the Gaussian hill has a finite width in
    1047             :                ! this direction
    1048             :                colvars(i)%ff_hills = colvars(i)%ff_hills + &
    1049      123800 :                                      ddp(i)/hills_env%delta_s_history(i, ih)*dfunc*cut_func
    1050      123800 :                IF (hills_env%tail_cutoff > 0.0_dp .AND. ABS(diff_ss(i)) > 10.E-5_dp) THEN
    1051             :                   colvars(i)%ff_hills = colvars(i)%ff_hills + &
    1052             :                                         (hills_env%p_exp*numf(i)/(1.0_dp - numf(i)) - hills_env%q_exp*denf(i)/(1.0_dp - denf(i)))* &
    1053       38006 :                                         dfunc*cut_func/ABS(diff_ss(i))
    1054             :                END IF
    1055             :             END IF
    1056             :          END DO
    1057             :       END DO
    1058       11278 :       DEALLOCATE (ddp)
    1059       11278 :       DEALLOCATE (diff_ss)
    1060       11278 :       DEALLOCATE (numf)
    1061       11278 :       DEALLOCATE (denf)
    1062             : 
    1063       11278 :       CALL cp_rm_iter_level(logger%iter_info, "METADYNAMICS")
    1064             : 
    1065       11278 :       CALL timestop(handle)
    1066             : 
    1067       22556 :    END SUBROUTINE hills
    1068             : 
    1069             : END MODULE metadynamics

Generated by: LCOV version 1.15