(git:6d276e9)
Loading...
Searching...
No Matches
al_system_dynamics.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \author Noam Bernstein [noamb] 02.2012
10! **************************************************************************************************
12
20 USE kinds, ONLY: dp
23 USE molecule_types, ONLY: get_molecule,&
28#include "../../base/base_uses.f90"
29
30 IMPLICIT NONE
31
32 PRIVATE
33 LOGICAL, PARAMETER :: debug_this_module = .false.
34 PUBLIC :: al_particles
35
36 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'al_system_dynamics'
37
38CONTAINS
39
40! **************************************************************************************************
41!> \brief ...
42!> \param al ...
43!> \param force_env ...
44!> \param molecule_kind_set ...
45!> \param molecule_set ...
46!> \param particle_set ...
47!> \param local_molecules ...
48!> \param local_particles ...
49!> \param group ...
50!> \param vel ...
51!> \author Noam Bernstein [noamb] 02.2012
52! **************************************************************************************************
53 SUBROUTINE al_particles(al, force_env, molecule_kind_set, molecule_set, &
54 particle_set, local_molecules, local_particles, group, vel)
55
56 TYPE(al_system_type), POINTER :: al
57 TYPE(force_env_type), POINTER :: force_env
58 TYPE(molecule_kind_type), POINTER :: molecule_kind_set(:)
59 TYPE(molecule_type), POINTER :: molecule_set(:)
60 TYPE(particle_type), POINTER :: particle_set(:)
61 TYPE(distribution_1d_type), POINTER :: local_molecules, local_particles
62 TYPE(mp_comm_type), INTENT(IN) :: group
63 REAL(kind=dp), INTENT(INOUT), OPTIONAL :: vel(:, :)
64
65 CHARACTER(len=*), PARAMETER :: routinen = 'al_particles'
66
67 INTEGER :: handle
68 LOGICAL :: my_shell_adiabatic
69 TYPE(map_info_type), POINTER :: map_info
70
71 CALL timeset(routinen, handle)
72 my_shell_adiabatic = .false.
73 map_info => al%map_info
74
75 IF (debug_this_module) THEN
76 CALL dump_vel(molecule_kind_set, molecule_set, local_molecules, particle_set, vel, "INIT")
77 END IF
78
79 IF (al%tau_nh <= 0.0_dp) THEN
80 CALL al_ou_step(0.5_dp, al, force_env, map_info, molecule_kind_set, molecule_set, &
81 particle_set, local_molecules, local_particles, vel)
82 IF (debug_this_module) THEN
83 CALL dump_vel(molecule_kind_set, molecule_set, local_molecules, particle_set, vel, "post OU")
84 END IF
85 ELSE
86 ! quarter step of Langevin using Ornstein-Uhlenbeck
87 CALL al_ou_step(0.25_dp, al, force_env, map_info, molecule_kind_set, molecule_set, &
88 particle_set, local_molecules, local_particles, vel)
89 IF (debug_this_module) THEN
90 CALL dump_vel(molecule_kind_set, molecule_set, local_molecules, particle_set, vel, "post 1st OU")
91 END IF
92
93 ! Compute the kinetic energy for the region to thermostat for the (T dependent chi step)
94 CALL ke_region_particles(map_info, particle_set, molecule_kind_set, &
95 local_molecules, molecule_set, group, vel=vel)
96 ! quarter step of chi, and set vel drag factors for a half step
97 CALL al_nh_quarter_step(al, map_info, set_half_step_vel_factors=.true.)
98
99 ! Now scale the particle velocities for a NH half step
100 CALL vel_rescale_particles(map_info, molecule_kind_set, molecule_set, particle_set, &
101 local_molecules, my_shell_adiabatic, vel=vel)
102 ! Recompute the kinetic energy for the region to thermostat (for the T dependent chi step)
103 CALL ke_region_particles(map_info, particle_set, molecule_kind_set, &
104 local_molecules, molecule_set, group, vel=vel)
105 IF (debug_this_module) THEN
106 CALL dump_vel(molecule_kind_set, molecule_set, local_molecules, particle_set, vel, "post rescale_vel")
107 END IF
108
109 ! quarter step of chi
110 CALL al_nh_quarter_step(al, map_info, set_half_step_vel_factors=.false.)
111
112 ! quarter step of Langevin using Ornstein-Uhlenbeck
113 CALL al_ou_step(0.25_dp, al, force_env, map_info, molecule_kind_set, molecule_set, &
114 particle_set, local_molecules, local_particles, vel)
115 IF (debug_this_module) THEN
116 CALL dump_vel(molecule_kind_set, molecule_set, local_molecules, particle_set, vel, "post 2nd OU")
117 END IF
118 END IF
119
120 ! Recompute the final kinetic energy for the region to thermostat
121 CALL ke_region_particles(map_info, particle_set, molecule_kind_set, &
122 local_molecules, molecule_set, group, vel=vel)
123
124 CALL timestop(handle)
125 END SUBROUTINE al_particles
126
127! **************************************************************************************************
128!> \brief ...
129!> \param molecule_kind_set ...
130!> \param molecule_set ...
131!> \param local_molecules ...
132!> \param particle_set ...
133!> \param vel ...
134!> \param label ...
135! **************************************************************************************************
136 SUBROUTINE dump_vel(molecule_kind_set, molecule_set, local_molecules, particle_set, vel, label)
137 TYPE(molecule_kind_type), POINTER :: molecule_kind_set(:)
138 TYPE(molecule_type), POINTER :: molecule_set(:)
139 TYPE(distribution_1d_type), POINTER :: local_molecules
140 TYPE(particle_type), POINTER :: particle_set(:)
141 REAL(dp), OPTIONAL :: vel(:, :)
142 CHARACTER(len=*) :: label
143
144 INTEGER :: first_atom, ikind, imol, imol_local, &
145 ipart, last_atom, nmol_local
146 TYPE(molecule_type), POINTER :: molecule
147
148 DO ikind = 1, SIZE(molecule_kind_set)
149 nmol_local = local_molecules%n_el(ikind)
150 DO imol_local = 1, nmol_local
151 imol = local_molecules%list(ikind)%array(imol_local)
152 molecule => molecule_set(imol)
153 CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
154 DO ipart = first_atom, last_atom
155 IF (PRESENT(vel)) THEN
156 WRITE (unit=*, fmt='("VEL ",A20," IPART ",I6," V ",3F20.10)') trim(label), ipart, vel(:, ipart)
157 ELSE
158 WRITE (unit=*, fmt='("PARTICLE_SET%VEL ",A20," IPART ",I6," V ",3F20.10)') trim(label), &
159 ipart, particle_set(ipart)%v(:)
160 END IF
161 END DO
162 END DO
163 END DO
164 END SUBROUTINE dump_vel
165
166! **************************************************************************************************
167!> \brief ...
168!> \param step ...
169!> \param al ...
170!> \param force_env ...
171!> \param map_info ...
172!> \param molecule_kind_set ...
173!> \param molecule_set ...
174!> \param particle_set ...
175!> \param local_molecules ...
176!> \param local_particles ...
177!> \param vel ...
178! **************************************************************************************************
179 SUBROUTINE al_ou_step(step, al, force_env, map_info, molecule_kind_set, molecule_set, &
180 particle_set, local_molecules, local_particles, vel)
181 REAL(dp), INTENT(in) :: step
182 TYPE(al_system_type), POINTER :: al
183 TYPE(force_env_type), POINTER :: force_env
184 TYPE(map_info_type), POINTER :: map_info
185 TYPE(molecule_kind_type), POINTER :: molecule_kind_set(:)
186 TYPE(molecule_type), POINTER :: molecule_set(:)
187 TYPE(particle_type), POINTER :: particle_set(:)
188 TYPE(distribution_1d_type), POINTER :: local_molecules, local_particles
189 REAL(kind=dp), INTENT(INOUT), OPTIONAL :: vel(:, :)
190
191 INTEGER :: first_atom, i, ii, ikind, imap, imol, imol_local, ipart, iparticle_kind, &
192 iparticle_local, jj, last_atom, nmol_local, nparticle, nparticle_kind, nparticle_local
193 LOGICAL :: check, present_vel
194 REAL(kind=dp) :: mass
195 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: w
196 TYPE(atomic_kind_type), POINTER :: atomic_kind
197 TYPE(molecule_type), POINTER :: molecule
198
199 present_vel = PRESENT(vel)
200
201 ![NB] not a big deal, but could this be done once at init time?
202 DO i = 1, al%loc_num_al
203 imap = map_info%map_index(i)
204 ! drag on velocities
205 IF (al%tau_langevin > 0.0_dp) THEN
206 map_info%v_scale(imap) = exp(-step*al%dt/al%tau_langevin)
207 map_info%s_kin(imap) = sqrt((al%nvt(i)%nkt/al%nvt(i)%degrees_of_freedom)*(1.0_dp - map_info%v_scale(imap)**2))
208 ELSE
209 map_info%v_scale(imap) = 1.0_dp
210 map_info%s_kin(imap) = 0.0_dp
211 END IF
212 ! magnitude of random force, not including 1/sqrt(mass) part
213 END DO
214
215 nparticle = SIZE(particle_set)
216 nparticle_kind = SIZE(local_particles%n_el)
217 ALLOCATE (w(3, nparticle))
218 w(:, :) = 0.0_dp
219 check = (nparticle_kind <= SIZE(local_particles%n_el) .AND. nparticle_kind <= SIZE(local_particles%list))
220 cpassert(check)
221 check = ASSOCIATED(local_particles%local_particle_set)
222 cpassert(check)
223 DO iparticle_kind = 1, nparticle_kind
224 nparticle_local = local_particles%n_el(iparticle_kind)
225 check = (nparticle_local <= SIZE(local_particles%list(iparticle_kind)%array))
226 cpassert(check)
227 DO iparticle_local = 1, nparticle_local
228 ipart = local_particles%list(iparticle_kind)%array(iparticle_local)
229 w(1, ipart) = local_particles%local_particle_set(iparticle_kind)%rng(iparticle_local)%stream%next(variance=1.0_dp)
230 w(2, ipart) = local_particles%local_particle_set(iparticle_kind)%rng(iparticle_local)%stream%next(variance=1.0_dp)
231 w(3, ipart) = local_particles%local_particle_set(iparticle_kind)%rng(iparticle_local)%stream%next(variance=1.0_dp)
232 END DO
233 END DO
234
235 CALL fix_atom_control(force_env, w)
236
237 ii = 0
238 DO ikind = 1, SIZE(molecule_kind_set)
239 nmol_local = local_molecules%n_el(ikind)
240 DO imol_local = 1, nmol_local
241 imol = local_molecules%list(ikind)%array(imol_local)
242 molecule => molecule_set(imol)
243 CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
244 DO ipart = first_atom, last_atom
245 ii = ii + 1
246 atomic_kind => particle_set(ipart)%atomic_kind
247 CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass)
248 IF (present_vel) THEN
249 DO jj = 1, 3
250 vel(jj, ipart) = vel(jj, ipart)*map_info%p_scale(jj, ii)%point + &
251 map_info%p_kin(jj, ii)%point/sqrt(mass)*w(jj, ipart)
252 END DO
253 ELSE
254 DO jj = 1, 3
255 particle_set(ipart)%v(jj) = particle_set(ipart)%v(jj)*map_info%p_scale(jj, ii)%point + &
256 map_info%p_kin(jj, ii)%point/sqrt(mass)*w(jj, ipart)
257 END DO
258 END IF
259 END DO
260 END DO
261 END DO
262
263 DEALLOCATE (w)
264
265 END SUBROUTINE al_ou_step
266
267! **************************************************************************************************
268!> \brief ...
269!> \param al ...
270!> \param map_info ...
271!> \param set_half_step_vel_factors ...
272!> \author Noam Bernstein [noamb] 02.2012
273! **************************************************************************************************
274 SUBROUTINE al_nh_quarter_step(al, map_info, set_half_step_vel_factors)
275 TYPE(al_system_type), POINTER :: al
276 TYPE(map_info_type), POINTER :: map_info
277 LOGICAL, INTENT(in) :: set_half_step_vel_factors
278
279 INTEGER :: i, imap
280 REAL(kind=dp) :: decay, delta_k
281
282![NB] how to deal with dt_fact?
283
284 DO i = 1, al%loc_num_al
285 IF (al%nvt(i)%mass > 0.0_dp) THEN
286 imap = map_info%map_index(i)
287 delta_k = 0.5_dp*(map_info%s_kin(imap) - al%nvt(i)%nkt)
288 al%nvt(i)%chi = al%nvt(i)%chi + 0.5_dp*al%dt*delta_k/al%nvt(i)%mass
289 IF (set_half_step_vel_factors) THEN
290 decay = exp(-0.5_dp*al%dt*al%nvt(i)%chi)
291 map_info%v_scale(imap) = decay
292 END IF
293 ELSE
294 al%nvt(i)%chi = 0.0_dp
295 IF (set_half_step_vel_factors) THEN
296 map_info%v_scale(imap) = 1.0_dp
297 END IF
298 END IF
299 END DO
300
301 END SUBROUTINE al_nh_quarter_step
302
303END MODULE al_system_dynamics
subroutine, public al_particles(al, force_env, molecule_kind_set, molecule_set, particle_set, local_molecules, local_particles, group, vel)
...
Type for the canonical sampling through velocity rescaling.
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind(atomic_kind, fist_potential, element_symbol, name, mass, kind_number, natom, atom_list, rcov, rvdw, z, qeff, apol, cpol, mm_radius, shell, shell_active, damping)
Get attributes of an atomic kind.
subroutine, public fix_atom_control(force_env, w)
allows for fix atom constraints
stores a lists of integer that are local to a processor. The idea is that these integers represent ob...
Lumps all possible extended system variables into one type for easy access and passing.
Interface for the force calculations.
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Interface to the message passing library MPI.
Define the molecule kind structure types and the corresponding functionality.
Define the data structure for the molecule information.
subroutine, public get_molecule(molecule, molecule_kind, lmi, lci, lg3x3, lg4x6, lcolv, first_atom, last_atom, first_shell, last_shell)
Get components from a molecule data set.
Define the data structure for the particle information.
Utilities for thermostats.
subroutine, public vel_rescale_particles(map_info, molecule_kind_set, molecule_set, particle_set, local_molecules, shell_adiabatic, shell_particle_set, core_particle_set, vel, shell_vel, core_vel)
...
subroutine, public ke_region_particles(map_info, particle_set, molecule_kind_set, local_molecules, molecule_set, group, vel)
...
Provides all information about an atomic kind.
structure to store local (to a processor) ordered lists of integers.
wrapper to abstract the force evaluation of the various methods