(git:b279b6b)
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-2024 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 
13  USE al_system_types, ONLY: al_system_type
14  USE atomic_kind_types, ONLY: atomic_kind_type,&
17  USE distribution_1d_types, ONLY: distribution_1d_type
18  USE extended_system_types, ONLY: map_info_type
19  USE force_env_types, ONLY: force_env_type
20  USE kinds, ONLY: dp
21  USE message_passing, ONLY: mp_comm_type
22  USE molecule_kind_types, ONLY: molecule_kind_type
23  USE molecule_types, ONLY: get_molecule,&
24  molecule_type
25  USE particle_types, ONLY: particle_type
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 
38 CONTAINS
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) &
76  CALL dump_vel(molecule_kind_set, molecule_set, local_molecules, particle_set, vel, "INIT")
77 
78  IF (al%tau_nh <= 0.0_dp) THEN
79  CALL al_ou_step(0.5_dp, al, force_env, map_info, molecule_kind_set, molecule_set, &
80  particle_set, local_molecules, local_particles, vel)
81  IF (debug_this_module) &
82  CALL dump_vel(molecule_kind_set, molecule_set, local_molecules, particle_set, vel, "post OU")
83  ELSE
84  ! quarter step of Langevin using Ornstein-Uhlenbeck
85  CALL al_ou_step(0.25_dp, al, force_env, map_info, molecule_kind_set, molecule_set, &
86  particle_set, local_molecules, local_particles, vel)
87  IF (debug_this_module) &
88  CALL dump_vel(molecule_kind_set, molecule_set, local_molecules, particle_set, vel, "post 1st OU")
89 
90  ! Compute the kinetic energy for the region to thermostat for the (T dependent chi step)
91  CALL ke_region_particles(map_info, particle_set, molecule_kind_set, &
92  local_molecules, molecule_set, group, vel=vel)
93  ! quarter step of chi, and set vel drag factors for a half step
94  CALL al_nh_quarter_step(al, map_info, set_half_step_vel_factors=.true.)
95 
96  ! Now scale the particle velocities for a NH half step
97  CALL vel_rescale_particles(map_info, molecule_kind_set, molecule_set, particle_set, &
98  local_molecules, my_shell_adiabatic, vel=vel)
99  ! Recompute the kinetic energy for the region to thermostat (for the T dependent chi step)
100  CALL ke_region_particles(map_info, particle_set, molecule_kind_set, &
101  local_molecules, molecule_set, group, vel=vel)
102  IF (debug_this_module) &
103  CALL dump_vel(molecule_kind_set, molecule_set, local_molecules, particle_set, vel, "post rescale_vel")
104 
105  ! quarter step of chi
106  CALL al_nh_quarter_step(al, map_info, set_half_step_vel_factors=.false.)
107 
108  ! quarter step of Langevin using Ornstein-Uhlenbeck
109  CALL al_ou_step(0.25_dp, al, force_env, map_info, molecule_kind_set, molecule_set, &
110  particle_set, local_molecules, local_particles, vel)
111  IF (debug_this_module) &
112  CALL dump_vel(molecule_kind_set, molecule_set, local_molecules, particle_set, vel, "post 2nd OU")
113  END IF
114 
115  ! Recompute the final kinetic energy for the region to thermostat
116  CALL ke_region_particles(map_info, particle_set, molecule_kind_set, &
117  local_molecules, molecule_set, group, vel=vel)
118 
119  CALL timestop(handle)
120  END SUBROUTINE al_particles
121 
122 ! **************************************************************************************************
123 !> \brief ...
124 !> \param molecule_kind_set ...
125 !> \param molecule_set ...
126 !> \param local_molecules ...
127 !> \param particle_set ...
128 !> \param vel ...
129 !> \param label ...
130 ! **************************************************************************************************
131  SUBROUTINE dump_vel(molecule_kind_set, molecule_set, local_molecules, particle_set, vel, label)
132  TYPE(molecule_kind_type), POINTER :: molecule_kind_set(:)
133  TYPE(molecule_type), POINTER :: molecule_set(:)
134  TYPE(distribution_1d_type), POINTER :: local_molecules
135  TYPE(particle_type), POINTER :: particle_set(:)
136  REAL(dp), OPTIONAL :: vel(:, :)
137  CHARACTER(len=*) :: label
138 
139  INTEGER :: first_atom, ikind, imol, imol_local, &
140  ipart, last_atom, nmol_local
141  TYPE(molecule_type), POINTER :: molecule
142 
143  DO ikind = 1, SIZE(molecule_kind_set)
144  nmol_local = local_molecules%n_el(ikind)
145  DO imol_local = 1, nmol_local
146  imol = local_molecules%list(ikind)%array(imol_local)
147  molecule => molecule_set(imol)
148  CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
149  DO ipart = first_atom, last_atom
150  IF (PRESENT(vel)) THEN
151  WRITE (unit=*, fmt='("VEL ",A20," IPART ",I6," V ",3F20.10)') trim(label), ipart, vel(:, ipart)
152  ELSE
153  WRITE (unit=*, fmt='("PARTICLE_SET%VEL ",A20," IPART ",I6," V ",3F20.10)') trim(label), &
154  ipart, particle_set(ipart)%v(:)
155  END IF
156  END DO
157  END DO
158  END DO
159  END SUBROUTINE dump_vel
160 
161 ! **************************************************************************************************
162 !> \brief ...
163 !> \param step ...
164 !> \param al ...
165 !> \param force_env ...
166 !> \param map_info ...
167 !> \param molecule_kind_set ...
168 !> \param molecule_set ...
169 !> \param particle_set ...
170 !> \param local_molecules ...
171 !> \param local_particles ...
172 !> \param vel ...
173 ! **************************************************************************************************
174  SUBROUTINE al_ou_step(step, al, force_env, map_info, molecule_kind_set, molecule_set, &
175  particle_set, local_molecules, local_particles, vel)
176  REAL(dp), INTENT(in) :: step
177  TYPE(al_system_type), POINTER :: al
178  TYPE(force_env_type), POINTER :: force_env
179  TYPE(map_info_type), POINTER :: map_info
180  TYPE(molecule_kind_type), POINTER :: molecule_kind_set(:)
181  TYPE(molecule_type), POINTER :: molecule_set(:)
182  TYPE(particle_type), POINTER :: particle_set(:)
183  TYPE(distribution_1d_type), POINTER :: local_molecules, local_particles
184  REAL(kind=dp), INTENT(INOUT), OPTIONAL :: vel(:, :)
185 
186  INTEGER :: first_atom, i, ii, ikind, imap, imol, imol_local, ipart, iparticle_kind, &
187  iparticle_local, jj, last_atom, nmol_local, nparticle, nparticle_kind, nparticle_local
188  LOGICAL :: check, present_vel
189  REAL(kind=dp) :: mass
190  REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: w(:, :)
191  TYPE(atomic_kind_type), POINTER :: atomic_kind
192  TYPE(molecule_type), POINTER :: molecule
193 
194  present_vel = PRESENT(vel)
195 
196  ![NB] not a big deal, but could this be done once at init time?
197  DO i = 1, al%loc_num_al
198  imap = map_info%map_index(i)
199  ! drag on velocities
200  IF (al%tau_langevin > 0.0_dp) THEN
201  map_info%v_scale(imap) = exp(-step*al%dt/al%tau_langevin)
202  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))
203  ELSE
204  map_info%v_scale(imap) = 1.0_dp
205  map_info%s_kin(imap) = 0.0_dp
206  END IF
207  ! magnitude of random force, not including 1/sqrt(mass) part
208  END DO
209 
210  nparticle = SIZE(particle_set)
211  nparticle_kind = SIZE(local_particles%n_el)
212  ALLOCATE (w(3, nparticle))
213  w(:, :) = 0.0_dp
214  check = (nparticle_kind <= SIZE(local_particles%n_el) .AND. nparticle_kind <= SIZE(local_particles%list))
215  cpassert(check)
216  check = ASSOCIATED(local_particles%local_particle_set)
217  cpassert(check)
218  DO iparticle_kind = 1, nparticle_kind
219  nparticle_local = local_particles%n_el(iparticle_kind)
220  check = (nparticle_local <= SIZE(local_particles%list(iparticle_kind)%array))
221  cpassert(check)
222  DO iparticle_local = 1, nparticle_local
223  ipart = local_particles%list(iparticle_kind)%array(iparticle_local)
224  w(1, ipart) = local_particles%local_particle_set(iparticle_kind)%rng(iparticle_local)%stream%next(variance=1.0_dp)
225  w(2, ipart) = local_particles%local_particle_set(iparticle_kind)%rng(iparticle_local)%stream%next(variance=1.0_dp)
226  w(3, ipart) = local_particles%local_particle_set(iparticle_kind)%rng(iparticle_local)%stream%next(variance=1.0_dp)
227  END DO
228  END DO
229 
230  CALL fix_atom_control(force_env, w)
231 
232  ii = 0
233  DO ikind = 1, SIZE(molecule_kind_set)
234  nmol_local = local_molecules%n_el(ikind)
235  DO imol_local = 1, nmol_local
236  imol = local_molecules%list(ikind)%array(imol_local)
237  molecule => molecule_set(imol)
238  CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
239  DO ipart = first_atom, last_atom
240  ii = ii + 1
241  atomic_kind => particle_set(ipart)%atomic_kind
242  CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass)
243  IF (present_vel) THEN
244  DO jj = 1, 3
245  vel(jj, ipart) = vel(jj, ipart)*map_info%p_scale(jj, ii)%point + &
246  map_info%p_kin(jj, ii)%point/sqrt(mass)*w(jj, ipart)
247  END DO
248  ELSE
249  DO jj = 1, 3
250  particle_set(ipart)%v(jj) = particle_set(ipart)%v(jj)*map_info%p_scale(jj, ii)%point + &
251  map_info%p_kin(jj, ii)%point/sqrt(mass)*w(jj, ipart)
252  END DO
253  END IF
254  END DO
255  END DO
256  END DO
257 
258  DEALLOCATE (w)
259 
260  END SUBROUTINE al_ou_step
261 
262 ! **************************************************************************************************
263 !> \brief ...
264 !> \param al ...
265 !> \param map_info ...
266 !> \param set_half_step_vel_factors ...
267 !> \author Noam Bernstein [noamb] 02.2012
268 ! **************************************************************************************************
269  SUBROUTINE al_nh_quarter_step(al, map_info, set_half_step_vel_factors)
270  TYPE(al_system_type), POINTER :: al
271  TYPE(map_info_type), POINTER :: map_info
272  LOGICAL, INTENT(in) :: set_half_step_vel_factors
273 
274  INTEGER :: i, imap
275  REAL(kind=dp) :: decay, delta_k
276 
277 ![NB] how to deal with dt_fact?
278 
279  DO i = 1, al%loc_num_al
280  IF (al%nvt(i)%mass > 0.0_dp) THEN
281  imap = map_info%map_index(i)
282  delta_k = 0.5_dp*(map_info%s_kin(imap) - al%nvt(i)%nkt)
283  al%nvt(i)%chi = al%nvt(i)%chi + 0.5_dp*al%dt*delta_k/al%nvt(i)%mass
284  IF (set_half_step_vel_factors) THEN
285  decay = exp(-0.5_dp*al%dt*al%nvt(i)%chi)
286  map_info%v_scale(imap) = decay
287  END IF
288  ELSE
289  al%nvt(i)%chi = 0.0_dp
290  IF (set_half_step_vel_factors) THEN
291  map_info%v_scale(imap) = 1.0_dp
292  END IF
293  END IF
294  END DO
295 
296  END SUBROUTINE al_nh_quarter_step
297 
298 END 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)
...