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 evaluations of colvar for internal coordinates schemes
10 : !> \par History
11 : !> 05-2007 created [tlaino]
12 : !> \author Teodoro Laino - Zurich University (2007) [tlaino]
13 : ! **************************************************************************************************
14 : MODULE colvar_utils
15 : USE cell_types, ONLY: cell_type
16 : USE colvar_methods, ONLY: colvar_eval_mol_f
17 : USE colvar_types, ONLY: &
18 : colvar_counters, colvar_setup, colvar_type, coord_colvar_id, distance_from_path_colvar_id, &
19 : gyration_colvar_id, mindist_colvar_id, population_colvar_id, reaction_path_colvar_id, &
20 : rmsd_colvar_id
21 : USE cp_subsys_types, ONLY: cp_subsys_get,&
22 : cp_subsys_type
23 : USE distribution_1d_types, ONLY: distribution_1d_type
24 : USE force_env_types, ONLY: force_env_get,&
25 : force_env_type
26 : USE input_constants, ONLY: rmsd_all,&
27 : rmsd_list
28 : USE kinds, ONLY: dp
29 : USE mathlib, ONLY: invert_matrix
30 : USE memory_utilities, ONLY: reallocate
31 : USE molecule_kind_list_types, ONLY: molecule_kind_list_type
32 : USE molecule_kind_types, ONLY: colvar_constraint_type,&
33 : fixd_constraint_type,&
34 : get_molecule_kind,&
35 : molecule_kind_type
36 : USE molecule_list_types, ONLY: molecule_list_type
37 : USE molecule_types, ONLY: get_molecule,&
38 : global_constraint_type,&
39 : local_colvar_constraint_type,&
40 : molecule_type
41 : USE particle_list_types, ONLY: particle_list_type
42 : USE particle_types, ONLY: particle_type
43 : USE rmsd, ONLY: rmsd3
44 : USE string_utilities, ONLY: uppercase
45 : USE util, ONLY: sort
46 : #include "./base/base_uses.f90"
47 :
48 : IMPLICIT NONE
49 :
50 : PRIVATE
51 : PUBLIC :: number_of_colvar, &
52 : eval_colvar, &
53 : set_colvars_target, &
54 : get_clv_force, &
55 : post_process_colvar
56 :
57 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'colvar_utils'
58 :
59 : CONTAINS
60 :
61 : ! **************************************************************************************************
62 : !> \brief Gives back the number of colvar defined for a force_eval
63 : !> \param force_env ...
64 : !> \param only_intra_colvar ...
65 : !> \param unique ...
66 : !> \return ...
67 : !> \author Teodoro Laino 05.2007 [tlaino] - Zurich University
68 : ! **************************************************************************************************
69 198 : FUNCTION number_of_colvar(force_env, only_intra_colvar, unique) RESULT(ntot)
70 : TYPE(force_env_type), POINTER :: force_env
71 : LOGICAL, INTENT(IN), OPTIONAL :: only_intra_colvar, unique
72 : INTEGER :: ntot
73 :
74 : CHARACTER(LEN=*), PARAMETER :: routineN = 'number_of_colvar'
75 :
76 : INTEGER :: handle, ikind, imol
77 : LOGICAL :: my_unique, skip_inter_colvar
78 : TYPE(colvar_counters) :: ncolv
79 : TYPE(cp_subsys_type), POINTER :: subsys
80 : TYPE(global_constraint_type), POINTER :: gci
81 : TYPE(molecule_kind_list_type), POINTER :: molecule_kinds
82 198 : TYPE(molecule_kind_type), POINTER :: molecule_kind, molecule_kind_set(:)
83 : TYPE(molecule_list_type), POINTER :: molecules
84 198 : TYPE(molecule_type), POINTER :: molecule, molecule_set(:)
85 :
86 198 : NULLIFY (subsys, molecules, molecule_kind, molecule, molecule_set, gci)
87 198 : CALL timeset(routineN, handle)
88 198 : skip_inter_colvar = .FALSE.
89 198 : my_unique = .FALSE.
90 198 : IF (PRESENT(only_intra_colvar)) skip_inter_colvar = only_intra_colvar
91 198 : IF (PRESENT(unique)) my_unique = unique
92 198 : ntot = 0
93 198 : CALL force_env_get(force_env=force_env, subsys=subsys)
94 : CALL cp_subsys_get(subsys=subsys, molecules=molecules, gci=gci, &
95 198 : molecule_kinds=molecule_kinds)
96 :
97 198 : molecule_set => molecules%els
98 : ! Intramolecular Colvar
99 198 : IF (my_unique) THEN
100 34 : molecule_kind_set => molecule_kinds%els
101 472 : DO ikind = 1, molecule_kinds%n_els
102 438 : molecule_kind => molecule_kind_set(ikind)
103 438 : CALL get_molecule_kind(molecule_kind, ncolv=ncolv)
104 472 : ntot = ntot + ncolv%ntot
105 : END DO
106 : ELSE
107 2456 : MOL: DO imol = 1, SIZE(molecule_set)
108 2292 : molecule => molecule_set(imol)
109 2292 : molecule_kind => molecule%molecule_kind
110 :
111 : CALL get_molecule_kind(molecule_kind, &
112 2292 : ncolv=ncolv)
113 2456 : ntot = ntot + ncolv%ntot
114 : END DO MOL
115 : END IF
116 : ! Intermolecular Colvar
117 198 : IF (.NOT. skip_inter_colvar) THEN
118 104 : IF (ASSOCIATED(gci)) THEN
119 104 : ntot = ntot + gci%ncolv%ntot
120 : END IF
121 : END IF
122 198 : CALL timestop(handle)
123 :
124 198 : END FUNCTION number_of_colvar
125 :
126 : ! **************************************************************************************************
127 : !> \brief Set the value of target for constraints/restraints
128 : !> \param targets ...
129 : !> \param force_env ...
130 : !> \author Teodoro Laino 05.2007 [tlaino] - Zurich University
131 : ! **************************************************************************************************
132 60 : SUBROUTINE set_colvars_target(targets, force_env)
133 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: targets
134 : TYPE(force_env_type), POINTER :: force_env
135 :
136 : CHARACTER(LEN=*), PARAMETER :: routineN = 'set_colvars_target'
137 :
138 : INTEGER :: handle, i, ikind, ind, nkind
139 : TYPE(cell_type), POINTER :: cell
140 : TYPE(colvar_constraint_type), DIMENSION(:), &
141 60 : POINTER :: colv_list
142 : TYPE(colvar_counters) :: ncolv
143 : TYPE(cp_subsys_type), POINTER :: subsys
144 : TYPE(global_constraint_type), POINTER :: gci
145 : TYPE(molecule_kind_list_type), POINTER :: molecule_kinds
146 : TYPE(molecule_kind_type), POINTER :: molecule_kind
147 :
148 60 : NULLIFY (cell, subsys, molecule_kinds, molecule_kind, gci, colv_list)
149 60 : CALL timeset(routineN, handle)
150 60 : CALL force_env_get(force_env=force_env, subsys=subsys, cell=cell)
151 60 : CALL cp_subsys_get(subsys=subsys, gci=gci, molecule_kinds=molecule_kinds)
152 :
153 60 : nkind = molecule_kinds%n_els
154 : ! Set Target for Intramolecular Colvars
155 120 : MOL: DO ikind = 1, nkind
156 60 : molecule_kind => molecule_kinds%els(ikind)
157 : CALL get_molecule_kind(molecule_kind, &
158 : colv_list=colv_list, &
159 60 : ncolv=ncolv)
160 120 : IF (ncolv%ntot /= 0) THEN
161 120 : DO i = 1, SIZE(colv_list)
162 60 : ind = colv_list(i)%inp_seq_num
163 120 : colv_list(i)%expected_value = targets(ind)
164 : END DO
165 : END IF
166 : END DO MOL
167 : ! Set Target for Intermolecular Colvars
168 60 : IF (ASSOCIATED(gci)) THEN
169 60 : IF (gci%ncolv%ntot /= 0) THEN
170 0 : colv_list => gci%colv_list
171 0 : DO i = 1, SIZE(colv_list)
172 0 : ind = colv_list(i)%inp_seq_num
173 0 : colv_list(i)%expected_value = targets(ind)
174 : END DO
175 : END IF
176 : END IF
177 60 : CALL timestop(handle)
178 :
179 60 : END SUBROUTINE set_colvars_target
180 :
181 : ! **************************************************************************************************
182 : !> \brief Computes the values of colvars and the Wilson matrix B and its invers A
183 : !> \param force_env ...
184 : !> \param coords ...
185 : !> \param cvalues ...
186 : !> \param Bmatrix ...
187 : !> \param MassI ...
188 : !> \param Amatrix ...
189 : !> \author Teodoro Laino 05.2007 [tlaino] - Zurich University
190 : ! **************************************************************************************************
191 94 : SUBROUTINE eval_colvar(force_env, coords, cvalues, Bmatrix, MassI, Amatrix)
192 :
193 : TYPE(force_env_type), POINTER :: force_env
194 : REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL :: coords
195 : REAL(KIND=dp), DIMENSION(:), INTENT(OUT) :: cvalues
196 : REAL(KIND=dp), DIMENSION(:, :), OPTIONAL, POINTER :: Bmatrix
197 : REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER :: MassI
198 : REAL(KIND=dp), DIMENSION(:, :), OPTIONAL, POINTER :: Amatrix
199 :
200 : CHARACTER(LEN=*), PARAMETER :: routineN = 'eval_colvar'
201 :
202 : INTEGER :: handle, i, ikind, imol, n_tot, natom, &
203 : nkind, nmol_per_kind, offset
204 94 : INTEGER, DIMENSION(:), POINTER :: map, wrk
205 : LOGICAL :: check
206 : REAL(KIND=dp) :: inv_error
207 94 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: bwrk, Gmatrix, Gmatrix_i
208 94 : REAL(KIND=dp), DIMENSION(:), POINTER :: rwrk
209 : TYPE(cell_type), POINTER :: cell
210 : TYPE(colvar_counters) :: ncolv
211 : TYPE(cp_subsys_type), POINTER :: subsys
212 : TYPE(distribution_1d_type), POINTER :: local_molecules
213 : TYPE(global_constraint_type), POINTER :: gci
214 : TYPE(molecule_kind_list_type), POINTER :: molecule_kinds
215 : TYPE(molecule_kind_type), POINTER :: molecule_kind
216 : TYPE(molecule_list_type), POINTER :: molecules
217 94 : TYPE(molecule_type), POINTER :: molecule, molecule_set(:)
218 : TYPE(particle_list_type), POINTER :: particles
219 94 : TYPE(particle_type), POINTER :: particle_set(:)
220 :
221 94 : NULLIFY (cell, subsys, local_molecules, molecule_kinds, &
222 94 : molecules, molecule_kind, molecule, &
223 94 : molecule_set, particles, particle_set, gci)
224 94 : IF (PRESENT(Bmatrix)) THEN
225 86 : check = ASSOCIATED(Bmatrix)
226 86 : CPASSERT(check)
227 423782 : Bmatrix = 0.0_dp
228 : END IF
229 94 : CALL timeset(routineN, handle)
230 282 : ALLOCATE (map(SIZE(cvalues)))
231 1410 : map = HUGE(0) ! init all, since used in a sort, but not all set in parallel.
232 94 : CALL force_env_get(force_env=force_env, subsys=subsys, cell=cell)
233 94 : n_tot = 0
234 1410 : cvalues = 0.0_dp
235 : CALL cp_subsys_get(subsys=subsys, &
236 : particles=particles, &
237 : molecules=molecules, &
238 : local_molecules=local_molecules, &
239 : gci=gci, &
240 94 : molecule_kinds=molecule_kinds)
241 :
242 94 : nkind = molecule_kinds%n_els
243 94 : particle_set => particles%els
244 94 : molecule_set => molecules%els
245 : ! Intramolecular Colvars
246 94 : IF (number_of_colvar(force_env, only_intra_colvar=.TRUE.) /= 0) THEN
247 474 : MOL: DO ikind = 1, nkind
248 380 : nmol_per_kind = local_molecules%n_el(ikind)
249 698 : DO imol = 1, nmol_per_kind
250 224 : i = local_molecules%list(ikind)%array(imol)
251 224 : molecule => molecule_set(i)
252 224 : molecule_kind => molecule%molecule_kind
253 :
254 : CALL get_molecule_kind(molecule_kind, &
255 224 : ncolv=ncolv)
256 224 : offset = get_colvar_offset(i, molecule_set)
257 : ! Collective variables
258 828 : IF (ncolv%ntot /= 0) THEN
259 : CALL eval_colv_int(molecule, particle_set, coords, cell, cvalues, &
260 328 : Bmatrix, offset, n_tot, map)
261 : END IF
262 : END DO
263 : END DO MOL
264 94 : CALL force_env%para_env%sum(n_tot)
265 2726 : CALL force_env%para_env%sum(cvalues)
266 847486 : IF (PRESENT(Bmatrix)) CALL force_env%para_env%sum(Bmatrix)
267 : END IF
268 94 : offset = n_tot
269 : ! Intermolecular Colvars
270 94 : IF (ASSOCIATED(gci)) THEN
271 94 : IF (gci%ncolv%ntot /= 0) THEN
272 : CALL eval_colv_ext(gci, particle_set, coords, cell, cvalues, &
273 0 : Bmatrix, offset, n_tot, map)
274 : END IF
275 : END IF
276 94 : CPASSERT(n_tot == SIZE(cvalues))
277 : ! Sort values of Collective Variables according the order of the input
278 : ! sections
279 188 : ALLOCATE (wrk(SIZE(cvalues)))
280 282 : ALLOCATE (rwrk(SIZE(cvalues)))
281 94 : CALL sort(map, SIZE(map), wrk)
282 1410 : rwrk = cvalues
283 1410 : DO i = 1, SIZE(wrk)
284 1410 : cvalues(i) = rwrk(wrk(i))
285 : END DO
286 : ! check and sort on Bmatrix
287 94 : IF (PRESENT(Bmatrix)) THEN
288 86 : check = n_tot == SIZE(Bmatrix, 2)
289 86 : CPASSERT(check)
290 344 : ALLOCATE (bwrk(SIZE(Bmatrix, 1), SIZE(Bmatrix, 2)))
291 423782 : bwrk(:, :) = Bmatrix
292 1394 : DO i = 1, SIZE(wrk)
293 423782 : Bmatrix(:, i) = bwrk(:, wrk(i))
294 : END DO
295 86 : DEALLOCATE (bwrk)
296 : END IF
297 94 : DEALLOCATE (rwrk)
298 94 : DEALLOCATE (wrk)
299 94 : DEALLOCATE (map)
300 : ! Construction of the Amatrix
301 94 : IF (PRESENT(Bmatrix) .AND. PRESENT(Amatrix)) THEN
302 60 : CPASSERT(ASSOCIATED(Amatrix))
303 60 : check = SIZE(Bmatrix, 1) == SIZE(Amatrix, 2)
304 60 : CPASSERT(check)
305 60 : check = SIZE(Bmatrix, 2) == SIZE(Amatrix, 1)
306 60 : CPASSERT(check)
307 240 : ALLOCATE (Gmatrix(n_tot, n_tot))
308 180 : ALLOCATE (Gmatrix_i(n_tot, n_tot))
309 6540 : Gmatrix(:, :) = MATMUL(TRANSPOSE(Bmatrix), Bmatrix)
310 60 : CALL invert_matrix(Gmatrix, Gmatrix_i, inv_error)
311 60 : IF (ABS(inv_error) > 1.0E-8_dp) &
312 0 : CPWARN("Error in inverting the Gmatrix larger than 1.0E-8!")
313 30720 : Amatrix = MATMUL(Gmatrix_i, TRANSPOSE(Bmatrix))
314 60 : DEALLOCATE (Gmatrix_i)
315 120 : DEALLOCATE (Gmatrix)
316 : END IF
317 94 : IF (PRESENT(MassI)) THEN
318 86 : natom = SIZE(particle_set)
319 86 : CPASSERT(ASSOCIATED(MassI))
320 86 : CPASSERT(SIZE(MassI) == natom*3)
321 4018 : DO i = 1, natom
322 3932 : MassI((i - 1)*3 + 1) = 1.0_dp/particle_set(i)%atomic_kind%mass
323 3932 : MassI((i - 1)*3 + 2) = 1.0_dp/particle_set(i)%atomic_kind%mass
324 4018 : MassI((i - 1)*3 + 3) = 1.0_dp/particle_set(i)%atomic_kind%mass
325 : END DO
326 : END IF
327 94 : CALL timestop(handle)
328 :
329 274 : END SUBROUTINE eval_colvar
330 :
331 : ! **************************************************************************************************
332 : !> \brief Computes the offset of the colvar for the specific molecule
333 : !> \param i ...
334 : !> \param molecule_set ...
335 : !> \return ...
336 : !> \author Teodoro Laino 05.2007 [tlaino] - Zurich University
337 : ! **************************************************************************************************
338 224 : FUNCTION get_colvar_offset(i, molecule_set) RESULT(offset)
339 : INTEGER, INTENT(IN) :: i
340 : TYPE(molecule_type), POINTER :: molecule_set(:)
341 : INTEGER :: offset
342 :
343 : INTEGER :: j
344 : TYPE(colvar_counters) :: ncolv
345 : TYPE(molecule_kind_type), POINTER :: molecule_kind
346 : TYPE(molecule_type), POINTER :: molecule
347 :
348 224 : offset = 0
349 1082 : DO j = 1, i - 1
350 858 : molecule => molecule_set(j)
351 858 : molecule_kind => molecule%molecule_kind
352 : CALL get_molecule_kind(molecule_kind, &
353 858 : ncolv=ncolv)
354 1082 : offset = offset + ncolv%ntot
355 : END DO
356 :
357 224 : END FUNCTION get_colvar_offset
358 :
359 : ! **************************************************************************************************
360 : !> \brief Computes Intramolecular colvar
361 : !> \param molecule ...
362 : !> \param particle_set ...
363 : !> \param coords ...
364 : !> \param cell ...
365 : !> \param cvalues ...
366 : !> \param Bmatrix ...
367 : !> \param offset ...
368 : !> \param n_tot ...
369 : !> \param map ...
370 : !> \author Teodoro Laino 05.2007 [tlaino] - Zurich University
371 : ! **************************************************************************************************
372 198 : SUBROUTINE eval_colv_int(molecule, particle_set, coords, cell, cvalues, &
373 : Bmatrix, offset, n_tot, map)
374 :
375 : TYPE(molecule_type), POINTER :: molecule
376 : TYPE(particle_type), POINTER :: particle_set(:)
377 : REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL :: coords
378 : TYPE(cell_type), POINTER :: cell
379 : REAL(KIND=dp), DIMENSION(:), INTENT(INOUT) :: cvalues
380 : REAL(KIND=dp), DIMENSION(:, :), OPTIONAL, POINTER :: Bmatrix
381 : INTEGER, INTENT(IN) :: offset
382 : INTEGER, INTENT(INOUT) :: n_tot
383 : INTEGER, DIMENSION(:), POINTER :: map
384 :
385 198 : TYPE(colvar_constraint_type), POINTER :: colv_list(:)
386 198 : TYPE(fixd_constraint_type), DIMENSION(:), POINTER :: fixd_list
387 198 : TYPE(local_colvar_constraint_type), POINTER :: lcolv(:)
388 : TYPE(molecule_kind_type), POINTER :: molecule_kind
389 :
390 198 : NULLIFY (fixd_list)
391 :
392 198 : molecule_kind => molecule%molecule_kind
393 198 : CALL get_molecule_kind(molecule_kind, colv_list=colv_list, fixd_list=fixd_list)
394 198 : CALL get_molecule(molecule, lcolv=lcolv)
395 : CALL eval_colv_low(colv_list, fixd_list, lcolv, particle_set, &
396 328 : coords, cell, cvalues, Bmatrix, offset, n_tot, map)
397 :
398 198 : END SUBROUTINE eval_colv_int
399 :
400 : ! **************************************************************************************************
401 : !> \brief Computes Intermolecular colvar
402 : !> \param gci ...
403 : !> \param particle_set ...
404 : !> \param coords ...
405 : !> \param cell ...
406 : !> \param cvalues ...
407 : !> \param Bmatrix ...
408 : !> \param offset ...
409 : !> \param n_tot ...
410 : !> \param map ...
411 : !> \author Teodoro Laino 05.2007 [tlaino] - Zurich University
412 : ! **************************************************************************************************
413 0 : SUBROUTINE eval_colv_ext(gci, particle_set, coords, cell, cvalues, &
414 : Bmatrix, offset, n_tot, map)
415 : TYPE(global_constraint_type), POINTER :: gci
416 : TYPE(particle_type), POINTER :: particle_set(:)
417 : REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL :: coords
418 : TYPE(cell_type), POINTER :: cell
419 : REAL(KIND=dp), DIMENSION(:), INTENT(INOUT) :: cvalues
420 : REAL(KIND=dp), DIMENSION(:, :), OPTIONAL, POINTER :: Bmatrix
421 : INTEGER, INTENT(IN) :: offset
422 : INTEGER, INTENT(INOUT) :: n_tot
423 : INTEGER, DIMENSION(:), POINTER :: map
424 :
425 : TYPE(colvar_constraint_type), POINTER :: colv_list(:)
426 : TYPE(fixd_constraint_type), DIMENSION(:), POINTER :: fixd_list
427 : TYPE(local_colvar_constraint_type), POINTER :: lcolv(:)
428 :
429 0 : colv_list => gci%colv_list
430 0 : fixd_list => gci%fixd_list
431 0 : lcolv => gci%lcolv
432 : CALL eval_colv_low(colv_list, fixd_list, lcolv, particle_set, &
433 0 : coords, cell, cvalues, Bmatrix, offset, n_tot, map)
434 :
435 0 : END SUBROUTINE eval_colv_ext
436 :
437 : ! **************************************************************************************************
438 : !> \brief Real evaluation of colvar and of the Wilson-Eliashevich Matrix
439 : !> B_ik : i: internal coordinates
440 : !> k: cartesian coordinates
441 : !> \param colv_list ...
442 : !> \param fixd_list ...
443 : !> \param lcolv ...
444 : !> \param particle_set ...
445 : !> \param coords ...
446 : !> \param cell ...
447 : !> \param cvalues ...
448 : !> \param Bmatrix ...
449 : !> \param offset ...
450 : !> \param n_tot ...
451 : !> \param map ...
452 : !> \author Teodoro Laino 05.2007 [tlaino] - Zurich University
453 : ! **************************************************************************************************
454 198 : SUBROUTINE eval_colv_low(colv_list, fixd_list, lcolv, particle_set, coords, &
455 198 : cell, cvalues, Bmatrix, offset, n_tot, map)
456 :
457 : TYPE(colvar_constraint_type), POINTER :: colv_list(:)
458 : TYPE(fixd_constraint_type), DIMENSION(:), POINTER :: fixd_list
459 : TYPE(local_colvar_constraint_type), POINTER :: lcolv(:)
460 : TYPE(particle_type), POINTER :: particle_set(:)
461 : REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL :: coords
462 : TYPE(cell_type), POINTER :: cell
463 : REAL(KIND=dp), DIMENSION(:), INTENT(INOUT) :: cvalues
464 : REAL(KIND=dp), DIMENSION(:, :), OPTIONAL, POINTER :: Bmatrix
465 : INTEGER, INTENT(IN) :: offset
466 : INTEGER, INTENT(INOUT) :: n_tot
467 : INTEGER, DIMENSION(:), POINTER :: map
468 :
469 : INTEGER :: iatm, iconst, ind, ival
470 :
471 198 : ival = offset
472 890 : DO iconst = 1, SIZE(colv_list)
473 692 : n_tot = n_tot + 1
474 692 : ival = ival + 1
475 : ! Update colvar
476 692 : IF (PRESENT(coords)) THEN
477 : CALL colvar_eval_mol_f(lcolv(iconst)%colvar, cell, particles=particle_set, &
478 204 : pos=RESHAPE(coords, (/3, SIZE(particle_set)/)), fixd_list=fixd_list)
479 : ELSE
480 : CALL colvar_eval_mol_f(lcolv(iconst)%colvar, cell, particles=particle_set, &
481 624 : fixd_list=fixd_list)
482 : END IF
483 692 : cvalues(ival) = lcolv(iconst)%colvar%ss
484 692 : map(ival) = colv_list(iconst)%inp_seq_num
485 : ! Build the Wilson-Eliashevich Matrix
486 890 : IF (PRESENT(Bmatrix)) THEN
487 2172 : DO iatm = 1, SIZE(lcolv(iconst)%colvar%i_atom)
488 1488 : ind = (lcolv(iconst)%colvar%i_atom(iatm) - 1)*3
489 1488 : Bmatrix(ind + 1, ival) = lcolv(iconst)%colvar%dsdr(1, iatm)
490 1488 : Bmatrix(ind + 2, ival) = lcolv(iconst)%colvar%dsdr(2, iatm)
491 2172 : Bmatrix(ind + 3, ival) = lcolv(iconst)%colvar%dsdr(3, iatm)
492 : END DO
493 : END IF
494 : END DO
495 :
496 198 : END SUBROUTINE eval_colv_low
497 :
498 : ! **************************************************************************************************
499 : !> \brief Computes the forces in the frame of collective variables, and additional
500 : !> also the local metric tensor
501 : !> \param force_env ...
502 : !> \param forces ...
503 : !> \param coords ...
504 : !> \param nsize_xyz ...
505 : !> \param nsize_int ...
506 : !> \param cvalues ...
507 : !> \param Mmatrix ...
508 : !> \author Teodoro Laino 05.2007
509 : ! **************************************************************************************************
510 86 : SUBROUTINE get_clv_force(force_env, forces, coords, nsize_xyz, nsize_int, cvalues, &
511 86 : Mmatrix)
512 : TYPE(force_env_type), POINTER :: force_env
513 : REAL(KIND=dp), DIMENSION(:), INTENT(INOUT), &
514 : OPTIONAL :: forces, coords
515 : INTEGER, INTENT(IN) :: nsize_xyz, nsize_int
516 : REAL(KIND=dp), DIMENSION(:), INTENT(OUT) :: cvalues, Mmatrix
517 :
518 : INTEGER :: i, j, k
519 : REAL(KIND=dp) :: tmp
520 86 : REAL(KIND=dp), DIMENSION(:), POINTER :: MassI, wrk
521 86 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: Amatrix, Bmatrix
522 :
523 344 : ALLOCATE (Bmatrix(nsize_xyz, nsize_int))
524 258 : ALLOCATE (MassI(nsize_xyz))
525 : ! Transform gradients if requested
526 86 : IF (PRESENT(forces)) THEN
527 180 : ALLOCATE (wrk(nsize_int))
528 180 : ALLOCATE (Amatrix(nsize_int, nsize_xyz))
529 : ! Compute the transformation matrices and the inverse mass diagonal Matrix
530 60 : CALL eval_colvar(force_env, coords, cvalues, Bmatrix, MassI, Amatrix)
531 15540 : wrk = MATMUL(Amatrix, forces)
532 3120 : forces = 0.0_dp
533 120 : forces(1:nsize_int) = wrk
534 60 : DEALLOCATE (Amatrix)
535 60 : DEALLOCATE (wrk)
536 : ELSE
537 : ! Compute the transformation matrices and the inverse mass diagonal Matrix
538 52 : CALL eval_colvar(force_env, coords, cvalues, Bmatrix, MassI)
539 : END IF
540 : ! Compute the Metric Tensor
541 1394 : DO i = 1, nsize_int
542 32030 : DO j = 1, i
543 : tmp = 0.0_dp
544 10307232 : DO k = 1, nsize_xyz
545 10307232 : tmp = tmp + Bmatrix(k, j)*MassI(k)*Bmatrix(k, i)
546 : END DO
547 30636 : Mmatrix((i - 1)*nsize_int + j) = tmp
548 31944 : Mmatrix((j - 1)*nsize_int + i) = tmp
549 : END DO
550 : END DO
551 86 : DEALLOCATE (MassI)
552 86 : DEALLOCATE (Bmatrix)
553 86 : END SUBROUTINE get_clv_force
554 :
555 : ! **************************************************************************************************
556 : !> \brief Complete the description of the COORDINATION colvar when
557 : !> defined using KINDS
558 : !> \param colvar ...
559 : !> \param particles ...
560 : !> \par History
561 : !> 1.2009 Fabio Sterpone : Added a part for population
562 : !> 10.2014 Moved out of colvar_types.F [Ole Schuett]
563 : !> \author Teodoro Laino - 07.2007
564 : ! **************************************************************************************************
565 912 : SUBROUTINE post_process_colvar(colvar, particles)
566 : TYPE(colvar_type), POINTER :: colvar
567 : TYPE(particle_type), DIMENSION(:), OPTIONAL, &
568 : POINTER :: particles
569 :
570 : CHARACTER(len=3) :: name_kind
571 : INTEGER :: i, ii, j, natoms, nkinds, nr_frame, stat
572 :
573 912 : natoms = SIZE(particles)
574 912 : IF (colvar%type_id == coord_colvar_id) THEN
575 54 : IF (colvar%coord_param%use_kinds_from .OR. colvar%coord_param%use_kinds_to) THEN
576 : ! Atoms from
577 6 : IF (colvar%coord_param%use_kinds_from) THEN
578 6 : colvar%coord_param%use_kinds_from = .FALSE.
579 6 : nkinds = SIZE(colvar%coord_param%c_kinds_from)
580 30 : DO i = 1, natoms
581 54 : DO j = 1, nkinds
582 24 : name_kind = TRIM(particles(i)%atomic_kind%name)
583 24 : CALL uppercase(name_kind)
584 48 : IF (TRIM(colvar%coord_param%c_kinds_from(j)) == name_kind) THEN
585 8 : CALL reallocate(colvar%coord_param%i_at_from, 1, colvar%coord_param%n_atoms_from + 1)
586 8 : colvar%coord_param%n_atoms_from = colvar%coord_param%n_atoms_from + 1
587 8 : colvar%coord_param%i_at_from(colvar%coord_param%n_atoms_from) = i
588 : END IF
589 : END DO
590 : END DO
591 6 : stat = colvar%coord_param%n_atoms_from
592 6 : CPASSERT(stat /= 0)
593 : END IF
594 : ! Atoms to
595 6 : IF (colvar%coord_param%use_kinds_to) THEN
596 6 : colvar%coord_param%use_kinds_to = .FALSE.
597 6 : nkinds = SIZE(colvar%coord_param%c_kinds_to)
598 30 : DO i = 1, natoms
599 54 : DO j = 1, nkinds
600 24 : name_kind = TRIM(particles(i)%atomic_kind%name)
601 24 : CALL uppercase(name_kind)
602 48 : IF (TRIM(colvar%coord_param%c_kinds_to(j)) == name_kind) THEN
603 10 : CALL reallocate(colvar%coord_param%i_at_to, 1, colvar%coord_param%n_atoms_to + 1)
604 10 : colvar%coord_param%n_atoms_to = colvar%coord_param%n_atoms_to + 1
605 10 : colvar%coord_param%i_at_to(colvar%coord_param%n_atoms_to) = i
606 : END IF
607 : END DO
608 : END DO
609 6 : stat = colvar%coord_param%n_atoms_to
610 6 : CPASSERT(stat /= 0)
611 : END IF
612 : ! Atoms to b
613 6 : IF (colvar%coord_param%use_kinds_to_b) THEN
614 2 : colvar%coord_param%use_kinds_to_b = .FALSE.
615 2 : nkinds = SIZE(colvar%coord_param%c_kinds_to_b)
616 8 : DO i = 1, natoms
617 14 : DO j = 1, nkinds
618 6 : name_kind = TRIM(particles(i)%atomic_kind%name)
619 6 : CALL uppercase(name_kind)
620 12 : IF (TRIM(colvar%coord_param%c_kinds_to_b(j)) == name_kind) THEN
621 2 : CALL reallocate(colvar%coord_param%i_at_to_b, 1, colvar%coord_param%n_atoms_to_b + 1)
622 2 : colvar%coord_param%n_atoms_to_b = colvar%coord_param%n_atoms_to_b + 1
623 2 : colvar%coord_param%i_at_to_b(colvar%coord_param%n_atoms_to_b) = i
624 : END IF
625 : END DO
626 : END DO
627 2 : stat = colvar%coord_param%n_atoms_to_b
628 2 : CPASSERT(stat /= 0)
629 : END IF
630 :
631 : ! Setup the colvar
632 6 : CALL colvar_setup(colvar)
633 : END IF
634 : END IF
635 :
636 912 : IF (colvar%type_id == mindist_colvar_id) THEN
637 0 : IF (colvar%mindist_param%use_kinds_from .OR. colvar%mindist_param%use_kinds_to) THEN
638 : ! Atoms from
639 0 : IF (colvar%mindist_param%use_kinds_from) THEN
640 0 : colvar%mindist_param%use_kinds_from = .FALSE.
641 0 : nkinds = SIZE(colvar%mindist_param%k_coord_from)
642 0 : DO i = 1, natoms
643 0 : DO j = 1, nkinds
644 0 : name_kind = TRIM(particles(i)%atomic_kind%name)
645 0 : CALL uppercase(name_kind)
646 0 : IF (TRIM(colvar%mindist_param%k_coord_from(j)) == name_kind) THEN
647 0 : CALL reallocate(colvar%mindist_param%i_coord_from, 1, colvar%mindist_param%n_coord_from + 1)
648 0 : colvar%mindist_param%n_coord_from = colvar%mindist_param%n_coord_from + 1
649 0 : colvar%mindist_param%i_coord_from(colvar%mindist_param%n_coord_from) = i
650 : END IF
651 : END DO
652 : END DO
653 0 : stat = colvar%mindist_param%n_coord_from
654 0 : CPASSERT(stat /= 0)
655 : END IF
656 : ! Atoms to
657 0 : IF (colvar%mindist_param%use_kinds_to) THEN
658 0 : colvar%mindist_param%use_kinds_to = .FALSE.
659 0 : nkinds = SIZE(colvar%mindist_param%k_coord_to)
660 0 : DO i = 1, natoms
661 0 : DO j = 1, nkinds
662 0 : name_kind = TRIM(particles(i)%atomic_kind%name)
663 0 : CALL uppercase(name_kind)
664 0 : IF (TRIM(colvar%mindist_param%k_coord_to(j)) == name_kind) THEN
665 0 : CALL reallocate(colvar%mindist_param%i_coord_to, 1, colvar%mindist_param%n_coord_to + 1)
666 0 : colvar%mindist_param%n_coord_to = colvar%mindist_param%n_coord_to + 1
667 0 : colvar%mindist_param%i_coord_to(colvar%mindist_param%n_coord_to) = i
668 : END IF
669 : END DO
670 : END DO
671 0 : stat = colvar%mindist_param%n_coord_to
672 0 : CPASSERT(stat /= 0)
673 : END IF
674 : ! Setup the colvar
675 0 : CALL colvar_setup(colvar)
676 : END IF
677 : END IF
678 :
679 912 : IF (colvar%type_id == population_colvar_id) THEN
680 :
681 8 : IF (colvar%population_param%use_kinds_from .OR. colvar%population_param%use_kinds_to) THEN
682 : ! Atoms from
683 8 : IF (colvar%population_param%use_kinds_from) THEN
684 0 : colvar%population_param%use_kinds_from = .FALSE.
685 0 : nkinds = SIZE(colvar%population_param%c_kinds_from)
686 0 : DO i = 1, natoms
687 0 : DO j = 1, nkinds
688 0 : name_kind = TRIM(particles(i)%atomic_kind%name)
689 0 : CALL uppercase(name_kind)
690 0 : IF (TRIM(colvar%population_param%c_kinds_from(j)) == name_kind) THEN
691 0 : CALL reallocate(colvar%population_param%i_at_from, 1, colvar%population_param%n_atoms_from + 1)
692 0 : colvar%population_param%n_atoms_from = colvar%population_param%n_atoms_from + 1
693 0 : colvar%population_param%i_at_from(colvar%population_param%n_atoms_from) = i
694 : END IF
695 : END DO
696 : END DO
697 0 : stat = colvar%population_param%n_atoms_from
698 0 : CPASSERT(stat /= 0)
699 : END IF
700 : ! Atoms to
701 8 : IF (colvar%population_param%use_kinds_to) THEN
702 8 : colvar%population_param%use_kinds_to = .FALSE.
703 8 : nkinds = SIZE(colvar%population_param%c_kinds_to)
704 32 : DO i = 1, natoms
705 56 : DO j = 1, nkinds
706 24 : name_kind = TRIM(particles(i)%atomic_kind%name)
707 24 : CALL uppercase(name_kind)
708 48 : IF (TRIM(colvar%population_param%c_kinds_to(j)) == name_kind) THEN
709 16 : CALL reallocate(colvar%population_param%i_at_to, 1, colvar%population_param%n_atoms_to + 1)
710 16 : colvar%population_param%n_atoms_to = colvar%population_param%n_atoms_to + 1
711 16 : colvar%population_param%i_at_to(colvar%population_param%n_atoms_to) = i
712 : END IF
713 : END DO
714 : END DO
715 8 : stat = colvar%population_param%n_atoms_to
716 8 : CPASSERT(stat /= 0)
717 : END IF
718 : ! Setup the colvar
719 8 : CALL colvar_setup(colvar)
720 : END IF
721 :
722 : END IF
723 :
724 912 : IF (colvar%type_id == gyration_colvar_id) THEN
725 :
726 2 : IF (colvar%gyration_param%use_kinds) THEN
727 : ! Atoms from
728 : IF (colvar%gyration_param%use_kinds) THEN
729 2 : colvar%gyration_param%use_kinds = .FALSE.
730 2 : nkinds = SIZE(colvar%gyration_param%c_kinds)
731 28 : DO i = 1, natoms
732 54 : DO j = 1, nkinds
733 26 : name_kind = TRIM(particles(i)%atomic_kind%name)
734 26 : CALL uppercase(name_kind)
735 52 : IF (TRIM(colvar%gyration_param%c_kinds(j)) == name_kind) THEN
736 26 : CALL reallocate(colvar%gyration_param%i_at, 1, colvar%gyration_param%n_atoms + 1)
737 26 : colvar%gyration_param%n_atoms = colvar%gyration_param%n_atoms + 1
738 26 : colvar%gyration_param%i_at(colvar%gyration_param%n_atoms) = i
739 : END IF
740 : END DO
741 : END DO
742 2 : stat = colvar%gyration_param%n_atoms
743 2 : CPASSERT(stat /= 0)
744 : END IF
745 : ! Setup the colvar
746 2 : CALL colvar_setup(colvar)
747 : END IF
748 : END IF
749 :
750 912 : IF (colvar%type_id == rmsd_colvar_id) THEN
751 4 : IF (colvar%rmsd_param%subset == rmsd_all .OR. colvar%rmsd_param%subset == rmsd_list) THEN
752 : ! weights are masses
753 28 : DO i = 1, SIZE(colvar%rmsd_param%i_rmsd)
754 24 : ii = colvar%rmsd_param%i_rmsd(i)
755 28 : colvar%rmsd_param%weights(ii) = particles(ii)%atomic_kind%mass
756 : END DO
757 : END IF
758 :
759 4 : IF (colvar%rmsd_param%align_frames) THEN
760 0 : nr_frame = SIZE(colvar%rmsd_param%r_ref, 2)
761 0 : DO i = 2, nr_frame
762 : CALL rmsd3(particles, colvar%rmsd_param%r_ref(:, i), colvar%rmsd_param%r_ref(:, 1), -1, &
763 0 : rotate=.TRUE.)
764 : END DO
765 : END IF
766 :
767 : END IF
768 :
769 912 : IF (colvar%type_id == distance_from_path_colvar_id .OR. colvar%type_id == reaction_path_colvar_id) THEN
770 20 : IF (colvar%reaction_path_param%dist_rmsd .OR. colvar%reaction_path_param%rmsd) THEN
771 8 : IF (colvar%reaction_path_param%align_frames) THEN
772 8 : nr_frame = colvar%reaction_path_param%nr_frames
773 40 : DO i = 2, nr_frame
774 : CALL rmsd3(particles, colvar%reaction_path_param%r_ref(:, i), colvar%reaction_path_param%r_ref(:, 1), -1, &
775 40 : rotate=.TRUE.)
776 : END DO
777 : END IF
778 : END IF
779 : END IF
780 :
781 912 : END SUBROUTINE post_process_colvar
782 :
783 60 : END MODULE colvar_utils
|