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 42535 : 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 42535 : 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 42535 : DIMENSION(:) :: pos_plumed_x, pos_plumed_y, pos_plumed_z
249 : REAL(KIND=dp), ALLOCATABLE, &
250 42535 : DIMENSION(:) :: force_plumed_x, force_plumed_y, force_plumed_z
251 : #endif
252 :
253 42535 : CALL timeset(routineN, handle)
254 :
255 : ! Apply Metadynamics
256 42535 : 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 42535 : CALL timestop(handle)
357 :
358 42535 : 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
|