Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \par History
10 : !> Harald Forbert (Dec-2000): Changes for multiple linked lists
11 : !> linklist_internal_data_type
12 : !> 07.02.2005: using real coordinates for r_last_update; cleaned (MK)
13 : !> \author CJM,MK
14 : ! **************************************************************************************************
15 : MODULE fist_neighbor_list_control
16 :
17 : USE atomic_kind_types, ONLY: atomic_kind_type,&
18 : get_atomic_kind_set
19 : USE cell_methods, ONLY: cell_create
20 : USE cell_types, ONLY: cell_clone,&
21 : cell_release,&
22 : cell_type,&
23 : pbc,&
24 : real_to_scaled,&
25 : scaled_to_real
26 : USE cp_log_handling, ONLY: cp_get_default_logger,&
27 : cp_logger_type
28 : USE cp_output_handling, ONLY: cp_print_key_finished_output,&
29 : cp_print_key_unit_nr
30 : USE distribution_1d_types, ONLY: distribution_1d_type
31 : USE exclusion_types, ONLY: exclusion_type
32 : USE fist_neighbor_list_types, ONLY: fist_neighbor_type
33 : USE fist_neighbor_lists, ONLY: build_fist_neighbor_lists
34 : USE fist_nonbond_env_types, ONLY: fist_nonbond_env_get,&
35 : fist_nonbond_env_set,&
36 : fist_nonbond_env_type,&
37 : pos_type
38 : USE input_section_types, ONLY: section_vals_type,&
39 : section_vals_val_get
40 : USE kinds, ONLY: dp
41 : USE message_passing, ONLY: mp_para_env_type
42 : USE pair_potential_types, ONLY: ace_type,&
43 : allegro_type,&
44 : gal21_type,&
45 : gal_type,&
46 : nequip_type,&
47 : pair_potential_pp_type,&
48 : siepmann_type,&
49 : tersoff_type
50 : USE particle_types, ONLY: particle_type
51 : #include "./base/base_uses.f90"
52 :
53 : IMPLICIT NONE
54 :
55 : PRIVATE
56 :
57 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'fist_neighbor_list_control'
58 :
59 : PUBLIC :: list_control
60 :
61 : !***
62 :
63 : CONTAINS
64 :
65 : ! to decide whether the neighbor list is to be updated or not
66 : ! based on a displacement criterion;
67 : ! if any particle has moved by 0.5*verlet_skin from the previous
68 : ! list update, then the list routine is called.
69 :
70 : ! **************************************************************************************************
71 : !> \brief ...
72 : !> \param atomic_kind_set ...
73 : !> \param particle_set ...
74 : !> \param local_particles ...
75 : !> \param cell ...
76 : !> \param fist_nonbond_env ...
77 : !> \param para_env ...
78 : !> \param mm_section ...
79 : !> \param shell_particle_set ...
80 : !> \param core_particle_set ...
81 : !> \param force_update ...
82 : !> \param exclusions ...
83 : ! **************************************************************************************************
84 415110 : SUBROUTINE list_control(atomic_kind_set, particle_set, local_particles, &
85 : cell, fist_nonbond_env, para_env, mm_section, shell_particle_set, &
86 83022 : core_particle_set, force_update, exclusions)
87 :
88 : TYPE(atomic_kind_type), POINTER :: atomic_kind_set(:)
89 : TYPE(particle_type), POINTER :: particle_set(:)
90 : TYPE(distribution_1d_type), POINTER :: local_particles
91 : TYPE(cell_type), POINTER :: cell
92 : TYPE(fist_nonbond_env_type), POINTER :: fist_nonbond_env
93 : TYPE(mp_para_env_type), POINTER :: para_env
94 : TYPE(section_vals_type), POINTER :: mm_section
95 : TYPE(particle_type), OPTIONAL, POINTER :: shell_particle_set(:), &
96 : core_particle_set(:)
97 : LOGICAL, INTENT(IN), OPTIONAL :: force_update
98 : TYPE(exclusion_type), DIMENSION(:), OPTIONAL :: exclusions
99 :
100 : CHARACTER(LEN=*), PARAMETER :: routineN = 'list_control'
101 :
102 : INTEGER :: counter, handle, ikind, iparticle, iparticle_kind, iparticle_local, ishell, &
103 : jkind, last_update, nparticle, nparticle_kind, nparticle_local, nshell, num_update, &
104 : output_unit
105 : LOGICAL :: build_from_scratch, geo_check, &
106 : shell_adiabatic, shell_present, &
107 : update_neighbor_lists
108 83022 : LOGICAL, DIMENSION(:, :), POINTER :: full_nl
109 : REAL(KIND=dp) :: aup, dr2, dr2_max, ei_scale14, lup, &
110 : vdw_scale14, verlet_skin
111 : REAL(KIND=dp), DIMENSION(3) :: dr, rab, rab_last_update, s, s2r
112 83022 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: rlist_cut, rlist_lowsq
113 : TYPE(cell_type), POINTER :: cell_last_update
114 : TYPE(cp_logger_type), POINTER :: logger
115 : TYPE(fist_neighbor_type), POINTER :: nonbonded
116 : TYPE(pair_potential_pp_type), POINTER :: potparm
117 83022 : TYPE(pos_type), DIMENSION(:), POINTER :: r_last_update, r_last_update_pbc, &
118 83022 : rcore_last_update_pbc, &
119 83022 : rshell_last_update_pbc
120 :
121 83022 : CALL timeset(routineN, handle)
122 83022 : NULLIFY (logger)
123 83022 : logger => cp_get_default_logger()
124 :
125 : ! *** Assigning local pointers ***
126 : CALL fist_nonbond_env_get(fist_nonbond_env, &
127 : nonbonded=nonbonded, &
128 : rlist_cut=rlist_cut, &
129 : rlist_lowsq=rlist_lowsq, &
130 : aup=aup, &
131 : lup=lup, &
132 : ei_scale14=ei_scale14, &
133 : vdw_scale14=vdw_scale14, &
134 : counter=counter, &
135 : r_last_update=r_last_update, &
136 : r_last_update_pbc=r_last_update_pbc, &
137 : rshell_last_update_pbc=rshell_last_update_pbc, &
138 : rcore_last_update_pbc=rcore_last_update_pbc, &
139 : cell_last_update=cell_last_update, &
140 : num_update=num_update, &
141 : potparm=potparm, &
142 83022 : last_update=last_update)
143 :
144 83022 : nparticle = SIZE(particle_set)
145 83022 : nparticle_kind = SIZE(atomic_kind_set)
146 83022 : nshell = 0
147 : CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, &
148 83022 : shell_present=shell_present, shell_adiabatic=shell_adiabatic)
149 83022 : IF (shell_present) THEN
150 9230 : nshell = SIZE(shell_particle_set)
151 : END IF
152 :
153 : ! *** Check, if the neighbor lists have to be built or updated ***
154 83022 : update_neighbor_lists = .FALSE.
155 : CALL section_vals_val_get(mm_section, "NEIGHBOR_LISTS%NEIGHBOR_LISTS_FROM_SCRATCH", &
156 83022 : l_val=build_from_scratch)
157 : CALL section_vals_val_get(mm_section, "NEIGHBOR_LISTS%GEO_CHECK", &
158 83022 : l_val=geo_check)
159 83022 : IF (ASSOCIATED(r_last_update)) THEN
160 : ! Determine the maximum of the squared displacement, compared to
161 : ! r_last_update.
162 : CALL section_vals_val_get(mm_section, "NEIGHBOR_LISTS%VERLET_SKIN", &
163 80517 : r_val=verlet_skin)
164 80517 : dr2_max = 0.0_dp
165 305685 : DO iparticle_kind = 1, nparticle_kind
166 225168 : nparticle_local = local_particles%n_el(iparticle_kind)
167 4650053 : DO iparticle_local = 1, nparticle_local
168 4344368 : iparticle = local_particles%list(iparticle_kind)%array(iparticle_local)
169 17377472 : s2r = r_last_update(iparticle)%r
170 17377472 : s = particle_set(iparticle)%r(:)
171 17377472 : dr(:) = s2r - s
172 4344368 : dr2 = dr(1)*dr(1) + dr(2)*dr(2) + dr(3)*dr(3)
173 4569536 : dr2_max = MAX(dr2_max, dr2)
174 : END DO
175 : END DO
176 :
177 80517 : CALL para_env%max(dr2_max)
178 :
179 : ! If the maximum distplacement is too large, ...
180 80517 : IF (dr2_max > 0.25_dp*verlet_skin**2 .OR. build_from_scratch) THEN
181 573889 : DO iparticle = 1, nparticle
182 4530422 : r_last_update(iparticle)%r = particle_set(iparticle)%r(:)
183 : END DO
184 : update_neighbor_lists = .TRUE.
185 : END IF
186 : ELSE
187 : ! There is no r_last_update to compare with. Neighbor lists from scratch.
188 615224 : ALLOCATE (r_last_update(nparticle))
189 602699 : DO iparticle = 1, nparticle
190 4804057 : r_last_update(iparticle)%r = particle_set(iparticle)%r(:)
191 : END DO
192 :
193 2505 : update_neighbor_lists = .TRUE.
194 2505 : build_from_scratch = .TRUE.
195 : END IF
196 : ! Force Update
197 83022 : IF (PRESENT(force_update)) THEN
198 0 : IF (force_update) update_neighbor_lists = .TRUE.
199 : END IF
200 :
201 : ! Allocate the r_last_update_pbc, rshell_last_update_pbc, rcore_last_update_pbc
202 83022 : IF (.NOT. ASSOCIATED(r_last_update_pbc)) THEN
203 615224 : ALLOCATE (r_last_update_pbc(nparticle))
204 : END IF
205 83022 : IF (shell_present .AND. .NOT. ASSOCIATED(rshell_last_update_pbc)) THEN
206 28934 : ALLOCATE (rshell_last_update_pbc(nshell))
207 : END IF
208 83022 : IF (shell_present .AND. .NOT. ASSOCIATED(rcore_last_update_pbc)) THEN
209 28934 : ALLOCATE (rcore_last_update_pbc(nshell))
210 : END IF
211 :
212 : ! update the neighbor lists
213 83022 : IF (update_neighbor_lists) THEN
214 : ! determine which pairs of atom kinds need full neighbor lists. Full
215 : ! means that atom a is in the neighbor list of atom b and vice versa.
216 44700 : ALLOCATE (full_nl(nparticle_kind, nparticle_kind))
217 11175 : IF (ASSOCIATED(potparm)) THEN
218 61308 : DO ikind = 1, nparticle_kind
219 741399 : DO jkind = ikind, nparticle_kind
220 680091 : full_nl(ikind, jkind) = .FALSE.
221 1360058 : IF (ANY(potparm%pot(ikind, jkind)%pot%type == tersoff_type)) THEN
222 132 : full_nl(ikind, jkind) = .TRUE.
223 : END IF
224 1360185 : IF (ANY(potparm%pot(ikind, jkind)%pot%type == siepmann_type)) THEN
225 5 : full_nl(ikind, jkind) = .TRUE.
226 : END IF
227 1360189 : IF (ANY(potparm%pot(ikind, jkind)%pot%type == gal_type)) THEN
228 1 : full_nl(ikind, jkind) = .TRUE.
229 : END IF
230 1360189 : IF (ANY(potparm%pot(ikind, jkind)%pot%type == gal21_type)) THEN
231 1 : full_nl(ikind, jkind) = .TRUE.
232 : END IF
233 1360178 : IF (ANY(potparm%pot(ikind, jkind)%pot%type == nequip_type)) THEN
234 12 : full_nl(ikind, jkind) = .TRUE.
235 : END IF
236 1360182 : IF (ANY(potparm%pot(ikind, jkind)%pot%type == allegro_type)) THEN
237 8 : full_nl(ikind, jkind) = .TRUE.
238 : END IF
239 1360148 : IF (ANY(potparm%pot(ikind, jkind)%pot%type == ace_type)) THEN
240 42 : full_nl(ikind, jkind) = .TRUE.
241 : END IF
242 730254 : full_nl(jkind, ikind) = full_nl(ikind, jkind)
243 : END DO
244 : END DO
245 : ELSE
246 178 : full_nl = .FALSE.
247 : END IF
248 : CALL build_fist_neighbor_lists(atomic_kind_set, particle_set, &
249 : local_particles, cell, rlist_cut, rlist_lowsq, ei_scale14, &
250 : vdw_scale14, nonbonded, para_env, &
251 : build_from_scratch=build_from_scratch, geo_check=geo_check, &
252 : mm_section=mm_section, full_nl=full_nl, &
253 11507 : exclusions=exclusions)
254 :
255 11175 : CALL cell_release(cell_last_update)
256 11175 : CALL cell_create(cell_last_update)
257 11175 : CALL cell_clone(cell, cell_last_update)
258 :
259 11175 : IF (counter > 0) THEN
260 8670 : num_update = num_update + 1
261 8670 : lup = counter + 1 - last_update
262 8670 : last_update = counter + 1
263 8670 : aup = aup + (lup - aup)/REAL(num_update, KIND=dp)
264 : ELSE
265 2505 : num_update = 0
266 2505 : lup = 0
267 2505 : last_update = 1
268 2505 : aup = 0.0_dp
269 : END IF
270 :
271 : CALL fist_nonbond_env_set(fist_nonbond_env, &
272 : lup=lup, &
273 : aup=aup, &
274 : r_last_update=r_last_update, &
275 : r_last_update_pbc=r_last_update_pbc, &
276 : rshell_last_update_pbc=rshell_last_update_pbc, &
277 : rcore_last_update_pbc=rcore_last_update_pbc, &
278 : nonbonded=nonbonded, &
279 : num_update=num_update, &
280 : last_update=last_update, &
281 11175 : cell_last_update=cell_last_update)
282 :
283 : output_unit = cp_print_key_unit_nr(logger, mm_section, "PRINT%NEIGHBOR_LISTS", &
284 11175 : extension=".mmLog")
285 11175 : IF (output_unit > 0) THEN
286 : WRITE (UNIT=output_unit, &
287 : FMT="(/,T2,A,/,T52,A,/,A,T31,A,T49,2(1X,F15.2),/,T2,A,/)") &
288 177 : REPEAT("*", 79), "INSTANTANEOUS AVERAGES", &
289 354 : " LIST UPDATES[steps]", "= ", lup, aup, REPEAT("*", 79)
290 : END IF
291 : CALL cp_print_key_finished_output(output_unit, logger, mm_section, &
292 11175 : "PRINT%NEIGHBOR_LISTS")
293 11175 : DEALLOCATE (full_nl)
294 : END IF
295 :
296 : ! Store particle positions after the last update, translated to the
297 : ! primitive cell, in r_last_update_pbc.
298 8366211 : DO iparticle = 1, nparticle
299 : ! The pbc algorithm is sensitive to numeric noise and compiler optimization because of ANINT.
300 : ! Therefore we need to call here exactly the same routine as in build_neighbor_lists.
301 33132756 : rab_last_update = pbc(r_last_update(iparticle)%r, cell_last_update) - r_last_update(iparticle)%r
302 8283189 : CALL real_to_scaled(s, rab_last_update, cell_last_update)
303 8283189 : CALL scaled_to_real(rab, s, cell)
304 :
305 66265512 : r_last_update_pbc(iparticle)%r = particle_set(iparticle)%r + rab
306 : ! Use the same translation for core and shell.
307 8283189 : ishell = particle_set(iparticle)%shell_index
308 8366211 : IF (ishell /= 0) THEN
309 6086768 : rshell_last_update_pbc(ishell)%r = rab + shell_particle_set(ishell)%r(:)
310 760846 : IF (shell_adiabatic) THEN
311 6086768 : rcore_last_update_pbc(ishell)%r = rab + core_particle_set(ishell)%r(:)
312 : ELSE
313 0 : rcore_last_update_pbc(ishell)%r = r_last_update_pbc(iparticle)%r(:)
314 : END IF
315 : END IF
316 : END DO
317 :
318 83022 : counter = counter + 1
319 83022 : CALL fist_nonbond_env_set(fist_nonbond_env, counter=counter)
320 83022 : CALL timestop(handle)
321 :
322 83022 : END SUBROUTINE list_control
323 :
324 : END MODULE fist_neighbor_list_control
|