1!--------------------------------------------------------------------------------------------------!
2!   CP2K: A general program to perform molecular dynamics simulations                              !
3!   Copyright (C) 2000 - 2020  CP2K developers group                                               !
4!--------------------------------------------------------------------------------------------------!
5
6! **************************************************************************************************
7!> \brief defines collective variables s({R}) and the derivative of this variable wrt R
8!>      these can then be used in constraints, restraints and metadynamics ...
9!> \par History
10!>      04.2004 created
11!>      01.2006 Refactored [Joost VandeVondele]
12!> \author Alessandro Laio,Fawzi Mohamed
13! **************************************************************************************************
14MODULE colvar_methods
15
16   USE cell_types,                      ONLY: cell_type,&
17                                              pbc
18   USE colvar_types,                    ONLY: &
19        HBP_colvar_id, Wc_colvar_id, acid_hyd_dist_colvar_id, acid_hyd_shell_colvar_id, &
20        angle_colvar_id, colvar_create, colvar_setup, colvar_type, combine_colvar_id, &
21        coord_colvar_id, dfunct_colvar_id, dist_colvar_id, distance_from_path_colvar_id, &
22        do_clv_fix_point, do_clv_geo_center, do_clv_x, do_clv_xy, do_clv_xz, do_clv_y, do_clv_yz, &
23        do_clv_z, eval_point_der, eval_point_mass, eval_point_pos, gyration_colvar_id, &
24        hydronium_dist_colvar_id, hydronium_shell_colvar_id, mindist_colvar_id, plane_def_atoms, &
25        plane_def_vec, plane_distance_colvar_id, plane_plane_angle_colvar_id, &
26        population_colvar_id, qparm_colvar_id, reaction_path_colvar_id, ring_puckering_colvar_id, &
27        rmsd_colvar_id, rotation_colvar_id, torsion_colvar_id, u_colvar_id, xyz_diag_colvar_id, &
28        xyz_outerdiag_colvar_id
29   USE constraint_fxd,                  ONLY: check_fixed_atom_cns_colv
30   USE cp_log_handling,                 ONLY: cp_get_default_logger,&
31                                              cp_logger_get_default_io_unit,&
32                                              cp_logger_type,&
33                                              cp_to_string
34   USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
35                                              cp_print_key_unit_nr
36   USE cp_para_types,                   ONLY: cp_para_env_type
37   USE cp_parser_methods,               ONLY: parser_get_next_line,&
38                                              parser_get_object
39   USE cp_parser_types,                 ONLY: cp_parser_type,&
40                                              parser_create,&
41                                              parser_release
42   USE cp_subsys_types,                 ONLY: cp_subsys_get,&
43                                              cp_subsys_p_type,&
44                                              cp_subsys_type
45   USE cp_units,                        ONLY: cp_unit_to_cp2k
46   USE force_env_types,                 ONLY: force_env_get,&
47                                              force_env_type,&
48                                              use_mixed_force
49   USE force_fields_util,               ONLY: get_generic_info
50   USE fparser,                         ONLY: EvalErrType,&
51                                              evalf,&
52                                              evalfd,&
53                                              finalizef,&
54                                              initf,&
55                                              parsef
56   USE input_constants,                 ONLY: rmsd_all,&
57                                              rmsd_list,&
58                                              rmsd_weightlist
59   USE input_cp2k_colvar,               ONLY: create_colvar_xyz_d_section,&
60                                              create_colvar_xyz_od_section
61   USE input_enumeration_types,         ONLY: enum_i2c,&
62                                              enumeration_type
63   USE input_keyword_types,             ONLY: keyword_get,&
64                                              keyword_type
65   USE input_section_types,             ONLY: section_get_keyword,&
66                                              section_release,&
67                                              section_type,&
68                                              section_vals_get,&
69                                              section_vals_get_subs_vals,&
70                                              section_vals_type,&
71                                              section_vals_val_get
72   USE kahan_sum,                       ONLY: accurate_sum
73   USE kinds,                           ONLY: default_path_length,&
74                                              default_string_length,&
75                                              dp
76   USE mathconstants,                   ONLY: fac,&
77                                              maxfac,&
78                                              pi,&
79                                              twopi
80   USE mathlib,                         ONLY: vector_product
81   USE memory_utilities,                ONLY: reallocate
82   USE message_passing,                 ONLY: mp_sum,&
83                                              mp_sync
84   USE mixed_energy_types,              ONLY: mixed_force_type
85   USE mixed_environment_utils,         ONLY: get_subsys_map_index
86   USE molecule_kind_types,             ONLY: fixd_constraint_type
87   USE particle_list_types,             ONLY: particle_list_p_type,&
88                                              particle_list_type
89   USE particle_types,                  ONLY: particle_type
90   USE qs_environment_types,            ONLY: get_qs_env,&
91                                              qs_environment_type
92   USE rmsd,                            ONLY: rmsd3
93   USE spherical_harmonics,             ONLY: dlegendre,&
94                                              legendre
95   USE string_utilities,                ONLY: compress,&
96                                              uppercase
97   USE wannier_states_types,            ONLY: wannier_centres_type
98#include "./base/base_uses.f90"
99
100   IMPLICIT NONE
101   PRIVATE
102
103   CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'colvar_methods'
104   REAL(KIND=dp), PRIVATE, PARAMETER    :: tolerance_acos = 1.0E-5_dp
105
106   PUBLIC :: colvar_read, &
107             colvar_eval_glob_f, &
108             colvar_eval_mol_f
109
110CONTAINS
111
112! **************************************************************************************************
113!> \brief reads a colvar from the input
114!> \param colvar the place where to store what will be read
115!> \param icol number of the current colvar (repetition in colvar_section)
116!> \param colvar_section the colvar section
117!> \param para_env ...
118!> \par History
119!>      04.2004 created [alessandro laio and fawzi mohamed]
120!> \author teo
121! **************************************************************************************************
122   RECURSIVE SUBROUTINE colvar_read(colvar, icol, colvar_section, para_env)
123      TYPE(colvar_type), POINTER                         :: colvar
124      INTEGER, INTENT(IN)                                :: icol
125      TYPE(section_vals_type), POINTER                   :: colvar_section
126      TYPE(cp_para_env_type), POINTER                    :: para_env
127
128      CHARACTER(len=*), PARAMETER :: routineN = 'colvar_read', routineP = moduleN//':'//routineN
129
130      CHARACTER(LEN=3)                                   :: fmid
131      CHARACTER(LEN=7)                                   :: tag, tag_comp, tag_comp1, tag_comp2
132      CHARACTER(LEN=default_path_length)                 :: path_function
133      CHARACTER(LEN=default_string_length)               :: tmpStr, tmpStr2
134      CHARACTER(LEN=default_string_length), &
135         DIMENSION(:), POINTER                           :: c_kinds, my_par
136      INTEGER                                            :: handle, i, iatm, icomponent, iend, &
137                                                            ifunc, ii, isize, istart, iw, iw1, j, &
138                                                            k, kk, n_var, n_var_k, ncol, ndim, &
139                                                            nr_frame, v_count
140      INTEGER, DIMENSION(:), POINTER                     :: iatms
141      INTEGER, DIMENSION(:, :), POINTER                  :: p_bounds
142      LOGICAL                                            :: check, use_mixed_energy
143      LOGICAL, DIMENSION(26)                             :: my_subsection
144      REAL(dp), DIMENSION(:), POINTER                    :: s1, wei, weights
145      REAL(dp), DIMENSION(:, :), POINTER                 :: p_range, s1v
146      REAL(KIND=dp), DIMENSION(1)                        :: my_val
147      REAL(KIND=dp), DIMENSION(:), POINTER               :: g_range, grid_point, grid_sp, my_vals, &
148                                                            range
149      TYPE(cp_logger_type), POINTER                      :: logger
150      TYPE(enumeration_type), POINTER                    :: enum
151      TYPE(keyword_type), POINTER                        :: keyword
152      TYPE(section_type), POINTER                        :: section
153      TYPE(section_vals_type), POINTER :: acid_hyd_dist_section, acid_hyd_shell_section, &
154         angle_section, colvar_subsection, combine_section, coordination_section, dfunct_section, &
155         distance_from_path_section, distance_section, frame_section, gyration_section, &
156         HBP_section, hydronium_dist_section, hydronium_shell_section, mindist_section, &
157         path_section, plane_dist_section, plane_plane_angle_section, plane_sections, &
158         point_section, population_section, qparm_section, reaction_path_section, &
159         ring_puckering_section, rmsd_section, rotation_section, torsion_section, u_section, &
160         Wc_section, wrk_section
161      TYPE(section_vals_type), POINTER :: xyz_diag_section, xyz_outerdiag_section
162
163      CALL timeset(routineN, handle)
164      NULLIFY (logger, c_kinds, iatms)
165      logger => cp_get_default_logger()
166      my_subsection = .FALSE.
167      distance_section => section_vals_get_subs_vals(colvar_section, "DISTANCE", i_rep_section=icol)
168      dfunct_section => section_vals_get_subs_vals(colvar_section, "DISTANCE_FUNCTION", &
169                                                   i_rep_section=icol)
170      angle_section => section_vals_get_subs_vals(colvar_section, "ANGLE", i_rep_section=icol)
171      torsion_section => section_vals_get_subs_vals(colvar_section, "TORSION", i_rep_section=icol)
172      coordination_section => section_vals_get_subs_vals(colvar_section, "COORDINATION", i_rep_section=icol)
173      plane_dist_section => section_vals_get_subs_vals(colvar_section, "DISTANCE_POINT_PLANE", i_rep_section=icol)
174      plane_plane_angle_section &
175         => section_vals_get_subs_vals(colvar_section, "ANGLE_PLANE_PLANE", i_rep_section=icol)
176      rotation_section => section_vals_get_subs_vals(colvar_section, "BOND_ROTATION", i_rep_section=icol)
177      qparm_section => section_vals_get_subs_vals(colvar_section, "QPARM", i_rep_section=icol)
178      hydronium_shell_section => section_vals_get_subs_vals(colvar_section, "HYDRONIUM_SHELL", i_rep_section=icol)
179      hydronium_dist_section => section_vals_get_subs_vals(colvar_section, "HYDRONIUM_DISTANCE", i_rep_section=icol)
180      acid_hyd_dist_section => section_vals_get_subs_vals(colvar_section, "ACID_HYDRONIUM_DISTANCE", i_rep_section=icol)
181      acid_hyd_shell_section &
182         => section_vals_get_subs_vals(colvar_section, "ACID_HYDRONIUM_SHELL", i_rep_section=icol)
183      reaction_path_section => section_vals_get_subs_vals(colvar_section, "REACTION_PATH", i_rep_section=icol, &
184                                                          can_return_null=.TRUE.)
185      distance_from_path_section &
186         => section_vals_get_subs_vals(colvar_section, "DISTANCE_FROM_PATH", &
187                                       i_rep_section=icol, can_return_null=.TRUE.)
188      combine_section => section_vals_get_subs_vals(colvar_section, "COMBINE_COLVAR", i_rep_section=icol, &
189                                                    can_return_null=.TRUE.)
190      population_section => section_vals_get_subs_vals(colvar_section, "POPULATION", i_rep_section=icol)
191      gyration_section => section_vals_get_subs_vals(colvar_section, "GYRATION_RADIUS", i_rep_section=icol)
192      rmsd_section => section_vals_get_subs_vals(colvar_section, "RMSD", i_rep_section=icol)
193      xyz_diag_section => section_vals_get_subs_vals(colvar_section, "XYZ_DIAG", i_rep_section=icol)
194      xyz_outerdiag_section => section_vals_get_subs_vals(colvar_section, "XYZ_OUTERDIAG", i_rep_section=icol)
195      u_section => section_vals_get_subs_vals(colvar_section, "U", i_rep_section=icol)
196      Wc_section => section_vals_get_subs_vals(colvar_section, "WC", i_rep_section=icol)
197      HBP_section => section_vals_get_subs_vals(colvar_section, "HBP", i_rep_section=icol)
198      ring_puckering_section &
199         => section_vals_get_subs_vals(colvar_section, "RING_PUCKERING", i_rep_section=icol)
200      mindist_section => section_vals_get_subs_vals(colvar_section, "CONDITIONED_DISTANCE", i_rep_section=icol)
201
202      CALL section_vals_get(distance_section, explicit=my_subsection(1))
203      CALL section_vals_get(angle_section, explicit=my_subsection(2))
204      CALL section_vals_get(torsion_section, explicit=my_subsection(3))
205      CALL section_vals_get(coordination_section, explicit=my_subsection(4))
206      CALL section_vals_get(plane_dist_section, explicit=my_subsection(5))
207      CALL section_vals_get(rotation_section, explicit=my_subsection(6))
208      CALL section_vals_get(dfunct_section, explicit=my_subsection(7))
209      CALL section_vals_get(qparm_section, explicit=my_subsection(8))
210      CALL section_vals_get(hydronium_shell_section, explicit=my_subsection(9))
211      ! These are just special cases since they are not present in their own defition of COLVARS
212      IF (ASSOCIATED(reaction_path_section)) THEN
213         CALL section_vals_get(reaction_path_section, &
214                               explicit=my_subsection(10))
215      END IF
216      IF (ASSOCIATED(distance_from_path_section)) THEN
217         CALL section_vals_get(distance_from_path_section, &
218                               explicit=my_subsection(16))
219      END IF
220      IF (ASSOCIATED(combine_section)) THEN
221         CALL section_vals_get(combine_section, explicit=my_subsection(11))
222      END IF
223      CALL section_vals_get(population_section, explicit=my_subsection(12))
224      CALL section_vals_get(plane_plane_angle_section, &
225                            explicit=my_subsection(13))
226      CALL section_vals_get(gyration_section, explicit=my_subsection(14))
227      CALL section_vals_get(rmsd_section, explicit=my_subsection(15))
228      CALL section_vals_get(xyz_diag_section, explicit=my_subsection(17))
229      CALL section_vals_get(xyz_outerdiag_section, explicit=my_subsection(18))
230      CALL section_vals_get(u_section, explicit=my_subsection(19))
231      CALL section_vals_get(Wc_section, explicit=my_subsection(20))
232      CALL section_vals_get(HBP_section, explicit=my_subsection(21))
233      CALL section_vals_get(ring_puckering_section, &
234                            explicit=my_subsection(22))
235      CALL section_vals_get(mindist_section, explicit=my_subsection(23))
236      CALL section_vals_get(acid_hyd_dist_section, explicit=my_subsection(24))
237      CALL section_vals_get(acid_hyd_shell_section, explicit=my_subsection(25))
238      CALL section_vals_get(hydronium_dist_section, explicit=my_subsection(26))
239
240      ! Only one colvar can be present
241      CPASSERT(COUNT(my_subsection) == 1)
242      CPASSERT(.NOT. ASSOCIATED(colvar))
243
244      IF (my_subsection(1)) THEN
245         ! Distance
246         wrk_section => distance_section
247         CALL colvar_create(colvar, dist_colvar_id)
248         CALL colvar_check_points(colvar, distance_section)
249         CALL section_vals_val_get(distance_section, "ATOMS", i_vals=iatms)
250         colvar%dist_param%i_at = iatms(1)
251         colvar%dist_param%j_at = iatms(2)
252         CALL section_vals_val_get(distance_section, "AXIS", i_val=colvar%dist_param%axis_id)
253      ELSE IF (my_subsection(2)) THEN
254         ! Angle
255         wrk_section => angle_section
256         CALL colvar_create(colvar, angle_colvar_id)
257         CALL colvar_check_points(colvar, angle_section)
258         CALL section_vals_val_get(angle_section, "ATOMS", i_vals=iatms)
259         colvar%angle_param%i_at_angle = iatms
260      ELSE IF (my_subsection(3)) THEN
261         ! Torsion
262         wrk_section => torsion_section
263         CALL colvar_create(colvar, torsion_colvar_id)
264         CALL colvar_check_points(colvar, torsion_section)
265         CALL section_vals_val_get(torsion_section, "ATOMS", i_vals=iatms)
266         colvar%torsion_param%i_at_tors = iatms
267         colvar%torsion_param%o0 = 0.0_dp
268      ELSE IF (my_subsection(4)) THEN
269         ! Coordination
270         wrk_section => coordination_section
271         CALL colvar_create(colvar, coord_colvar_id)
272         CALL colvar_check_points(colvar, coordination_section)
273         NULLIFY (colvar%coord_param%i_at_from, colvar%coord_param%c_kinds_from)
274         NULLIFY (colvar%coord_param%i_at_to, colvar%coord_param%c_kinds_to)
275         NULLIFY (colvar%coord_param%i_at_to_b, colvar%coord_param%c_kinds_to_b)
276         ! This section can be repeated
277         CALL section_vals_val_get(coordination_section, "ATOMS_FROM", n_rep_val=n_var)
278         ndim = 0
279         IF (n_var /= 0) THEN
280            ! INDEX LIST
281            DO k = 1, n_var
282               CALL section_vals_val_get(coordination_section, "ATOMS_FROM", i_rep_val=k, i_vals=iatms)
283               CALL reallocate(colvar%coord_param%i_at_from, 1, ndim + SIZE(iatms))
284               colvar%coord_param%i_at_from(ndim + 1:ndim + SIZE(iatms)) = iatms
285               ndim = ndim + SIZE(iatms)
286            END DO
287            colvar%coord_param%n_atoms_from = ndim
288            colvar%coord_param%use_kinds_from = .FALSE.
289         ELSE
290            ! KINDS
291            CALL section_vals_val_get(coordination_section, "KINDS_FROM", n_rep_val=n_var)
292            CPASSERT(n_var > 0)
293            DO k = 1, n_var
294               CALL section_vals_val_get(coordination_section, "KINDS_FROM", i_rep_val=k, c_vals=c_kinds)
295               CALL reallocate(colvar%coord_param%c_kinds_from, 1, ndim + SIZE(c_kinds))
296               colvar%coord_param%c_kinds_from(ndim + 1:ndim + SIZE(c_kinds)) = c_kinds
297               ndim = ndim + SIZE(c_kinds)
298            END DO
299            colvar%coord_param%n_atoms_from = 0
300            colvar%coord_param%use_kinds_from = .TRUE.
301            ! Uppercase the label
302            DO k = 1, ndim
303               CALL uppercase(colvar%coord_param%c_kinds_from(k))
304            END DO
305         END IF
306         ! This section can be repeated
307         CALL section_vals_val_get(coordination_section, "ATOMS_TO", n_rep_val=n_var)
308         ndim = 0
309         IF (n_var /= 0) THEN
310            ! INDEX LIST
311            DO k = 1, n_var
312               CALL section_vals_val_get(coordination_section, "ATOMS_TO", i_rep_val=k, i_vals=iatms)
313               CALL reallocate(colvar%coord_param%i_at_to, 1, ndim + SIZE(iatms))
314               colvar%coord_param%i_at_to(ndim + 1:ndim + SIZE(iatms)) = iatms
315               ndim = ndim + SIZE(iatms)
316            END DO
317            colvar%coord_param%n_atoms_to = ndim
318            colvar%coord_param%use_kinds_to = .FALSE.
319         ELSE
320            ! KINDS
321            CALL section_vals_val_get(coordination_section, "KINDS_TO", n_rep_val=n_var)
322            CPASSERT(n_var > 0)
323            DO k = 1, n_var
324               CALL section_vals_val_get(coordination_section, "KINDS_TO", i_rep_val=k, c_vals=c_kinds)
325               CALL reallocate(colvar%coord_param%c_kinds_to, 1, ndim + SIZE(c_kinds))
326               colvar%coord_param%c_kinds_to(ndim + 1:ndim + SIZE(c_kinds)) = c_kinds
327               ndim = ndim + SIZE(c_kinds)
328            END DO
329            colvar%coord_param%n_atoms_to = 0
330            colvar%coord_param%use_kinds_to = .TRUE.
331            ! Uppercase the label
332            DO k = 1, ndim
333               CALL uppercase(colvar%coord_param%c_kinds_to(k))
334            END DO
335         END IF
336         ! Let's finish reading the other parameters
337         CALL section_vals_val_get(coordination_section, "R0", r_val=colvar%coord_param%r_0)
338         CALL section_vals_val_get(coordination_section, "NN", i_val=colvar%coord_param%nncrd)
339         CALL section_vals_val_get(coordination_section, "ND", i_val=colvar%coord_param%ndcrd)
340         ! This section can be repeated
341         CALL section_vals_val_get(coordination_section, "ATOMS_TO_B", n_rep_val=n_var)
342         CALL section_vals_val_get(coordination_section, "KINDS_TO_B", n_rep_val=n_var_k)
343         ndim = 0
344         IF (n_var /= 0 .OR. n_var_k /= 0) THEN
345            colvar%coord_param%do_chain = .TRUE.
346            IF (n_var /= 0) THEN
347               ! INDEX LIST
348               DO k = 1, n_var
349                  CALL section_vals_val_get(coordination_section, "ATOMS_TO_B", i_rep_val=k, i_vals=iatms)
350                  CALL reallocate(colvar%coord_param%i_at_to_b, 1, ndim + SIZE(iatms))
351                  colvar%coord_param%i_at_to_b(ndim + 1:ndim + SIZE(iatms)) = iatms
352                  ndim = ndim + SIZE(iatms)
353               END DO
354               colvar%coord_param%n_atoms_to_b = ndim
355               colvar%coord_param%use_kinds_to_b = .FALSE.
356            ELSE
357               ! KINDS
358               CALL section_vals_val_get(coordination_section, "KINDS_TO_B", n_rep_val=n_var_k)
359               CPASSERT(n_var_k > 0)
360               DO k = 1, n_var_k
361                  CALL section_vals_val_get(coordination_section, "KINDS_TO_B", i_rep_val=k, c_vals=c_kinds)
362                  CALL reallocate(colvar%coord_param%c_kinds_to_b, 1, ndim + SIZE(c_kinds))
363                  colvar%coord_param%c_kinds_to_b(ndim + 1:ndim + SIZE(c_kinds)) = c_kinds
364                  ndim = ndim + SIZE(c_kinds)
365               END DO
366               colvar%coord_param%n_atoms_to_b = 0
367               colvar%coord_param%use_kinds_to_b = .TRUE.
368               ! Uppercase the label
369               DO k = 1, ndim
370                  CALL uppercase(colvar%coord_param%c_kinds_to_b(k))
371               END DO
372            END IF
373            ! Let's finish reading the other parameters
374            CALL section_vals_val_get(coordination_section, "R0_B", r_val=colvar%coord_param%r_0_b)
375            CALL section_vals_val_get(coordination_section, "NN_B", i_val=colvar%coord_param%nncrd_b)
376            CALL section_vals_val_get(coordination_section, "ND_B", i_val=colvar%coord_param%ndcrd_b)
377         ELSE
378            colvar%coord_param%do_chain = .FALSE.
379            colvar%coord_param%n_atoms_to_b = 0
380            colvar%coord_param%use_kinds_to_b = .FALSE.
381            NULLIFY (colvar%coord_param%i_at_to_b)
382            NULLIFY (colvar%coord_param%c_kinds_to_b)
383            colvar%coord_param%nncrd_b = 0
384            colvar%coord_param%ndcrd_b = 0
385            colvar%coord_param%r_0_b = 0._dp
386         END IF
387
388      ELSE IF (my_subsection(5)) THEN
389         ! Distance point from plane
390         wrk_section => plane_dist_section
391         CALL colvar_create(colvar, plane_distance_colvar_id)
392         CALL colvar_check_points(colvar, plane_dist_section)
393         CALL section_vals_val_get(plane_dist_section, "ATOMS_PLANE", i_vals=iatms)
394         CPASSERT(SIZE(iatms) == 3)
395         colvar%plane_distance_param%plane = iatms
396         CALL section_vals_val_get(plane_dist_section, "ATOM_POINT", i_val=iatm)
397         colvar%plane_distance_param%point = iatm
398         CALL section_vals_val_get(plane_dist_section, "PBC", l_val=colvar%plane_distance_param%use_pbc)
399      ELSE IF (my_subsection(6)) THEN
400         ! Rotation colvar of a segment w.r.t. another segment
401         wrk_section => rotation_section
402         CALL colvar_create(colvar, rotation_colvar_id)
403         CALL colvar_check_points(colvar, rotation_section)
404         CALL section_vals_val_get(rotation_section, "P1_BOND1", i_val=colvar%rotation_param%i_at1_bond1)
405         CALL section_vals_val_get(rotation_section, "P2_BOND1", i_val=colvar%rotation_param%i_at2_bond1)
406         CALL section_vals_val_get(rotation_section, "P1_BOND2", i_val=colvar%rotation_param%i_at1_bond2)
407         CALL section_vals_val_get(rotation_section, "P2_BOND2", i_val=colvar%rotation_param%i_at2_bond2)
408      ELSE IF (my_subsection(7)) THEN
409         ! Difference of two distances
410         wrk_section => dfunct_section
411         CALL colvar_create(colvar, dfunct_colvar_id)
412         CALL colvar_check_points(colvar, dfunct_section)
413         CALL section_vals_val_get(dfunct_section, "ATOMS", i_vals=iatms)
414         colvar%dfunct_param%i_at_dfunct = iatms
415         CALL section_vals_val_get(dfunct_section, "COEFFICIENT", r_val=colvar%dfunct_param%coeff)
416         CALL section_vals_val_get(dfunct_section, "PBC", l_val=colvar%dfunct_param%use_pbc)
417      ELSE IF (my_subsection(8)) THEN
418         ! Q Parameter
419         wrk_section => qparm_section
420         CALL colvar_create(colvar, qparm_colvar_id)
421         CALL colvar_check_points(colvar, qparm_section)
422         CALL section_vals_val_get(qparm_section, "RCUT", r_val=colvar%qparm_param%rcut)
423         CALL section_vals_val_get(qparm_section, "RSTART", r_val=colvar%qparm_param%rstart)
424         CALL section_vals_val_get(qparm_section, "INCLUDE_IMAGES", l_val=colvar%qparm_param%include_images)
425         !CALL section_vals_val_get(qparm_section, "ALPHA", r_val=colvar%qparm_param%alpha)
426         CALL section_vals_val_get(qparm_section, "L", i_val=colvar%qparm_param%l)
427         NULLIFY (colvar%qparm_param%i_at_from)
428         NULLIFY (colvar%qparm_param%i_at_to)
429         CALL section_vals_val_get(qparm_section, "ATOMS_FROM", n_rep_val=n_var)
430         ndim = 0
431         DO k = 1, n_var
432            CALL section_vals_val_get(qparm_section, "ATOMS_FROM", i_rep_val=k, i_vals=iatms)
433            CALL reallocate(colvar%qparm_param%i_at_from, 1, ndim + SIZE(iatms))
434            colvar%qparm_param%i_at_from(ndim + 1:ndim + SIZE(iatms)) = iatms
435            ndim = ndim + SIZE(iatms)
436         END DO
437         colvar%qparm_param%n_atoms_from = ndim
438         ! This section can be repeated
439         CALL section_vals_val_get(qparm_section, "ATOMS_TO", n_rep_val=n_var)
440         ndim = 0
441         DO k = 1, n_var
442            CALL section_vals_val_get(qparm_section, "ATOMS_TO", i_rep_val=k, i_vals=iatms)
443            CALL reallocate(colvar%qparm_param%i_at_to, 1, ndim + SIZE(iatms))
444            colvar%qparm_param%i_at_to(ndim + 1:ndim + SIZE(iatms)) = iatms
445            ndim = ndim + SIZE(iatms)
446         END DO
447         colvar%qparm_param%n_atoms_to = ndim
448      ELSE IF (my_subsection(9)) THEN
449         ! Hydronium
450         CALL colvar_create(colvar, hydronium_shell_colvar_id)
451         NULLIFY (colvar%hydronium_shell_param%i_oxygens)
452         NULLIFY (colvar%hydronium_shell_param%i_hydrogens)
453         CALL read_hydronium_colvars(hydronium_shell_section, colvar, hydronium_shell_colvar_id, &
454                                     colvar%hydronium_shell_param%n_oxygens, &
455                                     colvar%hydronium_shell_param%n_hydrogens, &
456                                     colvar%hydronium_shell_param%i_oxygens, &
457                                     colvar%hydronium_shell_param%i_hydrogens)
458      ELSE IF (my_subsection(10) .OR. my_subsection(16)) THEN
459         !reaction path or distance from reaction path
460         IF (my_subsection(10)) THEN
461            path_section => reaction_path_section
462            CALL colvar_create(colvar, reaction_path_colvar_id)
463            fmid = "POS"
464            ifunc = 1
465         ELSE IF (my_subsection(16)) THEN
466            path_section => distance_from_path_section
467            CALL colvar_create(colvar, distance_from_path_colvar_id)
468            fmid = "DIS"
469            ifunc = 2
470         END IF
471         colvar%use_points = .FALSE.
472         CALL section_vals_val_get(path_section, "LAMBDA", r_val=colvar%reaction_path_param%lambda)
473         CALL section_vals_val_get(path_section, "DISTANCES_RMSD", l_val=colvar%reaction_path_param%dist_rmsd)
474         CALL section_vals_val_get(path_section, "RMSD", l_val=colvar%reaction_path_param%rmsd)
475         IF (colvar%reaction_path_param%dist_rmsd .AND. colvar%reaction_path_param%rmsd) THEN
476            CPABORT("CV REACTION PATH: only one between DISTANCES_RMSD and RMSD can be used ")
477         END IF
478         IF (colvar%reaction_path_param%dist_rmsd .OR. colvar%reaction_path_param%rmsd) THEN
479            NULLIFY (colvar%reaction_path_param%i_rmsd, colvar%reaction_path_param%r_ref)
480            frame_section => section_vals_get_subs_vals(path_section, "FRAME")
481            CALL section_vals_get(frame_section, n_repetition=nr_frame)
482
483            colvar%reaction_path_param%nr_frames = nr_frame
484            CALL read_frames(frame_section, para_env, nr_frame, colvar%reaction_path_param%r_ref, &
485                             colvar%reaction_path_param%n_components)
486            CALL section_vals_val_get(path_section, "SUBSET_TYPE", i_val=colvar%reaction_path_param%subset)
487            IF (colvar%reaction_path_param%subset == rmsd_all) THEN
488               ALLOCATE (colvar%reaction_path_param%i_rmsd(colvar%reaction_path_param%n_components))
489               DO i = 1, colvar%reaction_path_param%n_components
490                  colvar%reaction_path_param%i_rmsd(i) = i
491               END DO
492            ELSE IF (colvar%reaction_path_param%subset == rmsd_list) THEN
493               ! This section can be repeated
494               CALL section_vals_val_get(path_section, "ATOMS", n_rep_val=n_var)
495               ndim = 0
496               IF (n_var /= 0) THEN
497                  ! INDEX LIST
498                  DO k = 1, n_var
499                     CALL section_vals_val_get(path_section, "ATOMS", i_rep_val=k, i_vals=iatms)
500                     CALL reallocate(colvar%reaction_path_param%i_rmsd, 1, ndim + SIZE(iatms))
501                     colvar%reaction_path_param%i_rmsd(ndim + 1:ndim + SIZE(iatms)) = iatms
502                     ndim = ndim + SIZE(iatms)
503                  END DO
504                  colvar%reaction_path_param%n_components = ndim
505               ELSE
506                  CPABORT("CV REACTION PATH: if SUBSET_TYPE=LIST a list of atoms needs to be provided ")
507               END IF
508            END IF
509
510            CALL section_vals_val_get(path_section, "ALIGN_FRAMES", l_val=colvar%reaction_path_param%align_frames)
511         ELSE
512            colvar_subsection => section_vals_get_subs_vals(path_section, "COLVAR")
513            CALL section_vals_get(colvar_subsection, n_repetition=ncol)
514            ALLOCATE (colvar%reaction_path_param%colvar_p(ncol))
515            IF (ncol > 0) THEN
516               DO i = 1, ncol
517                  NULLIFY (colvar%reaction_path_param%colvar_p(i)%colvar)
518                  CALL colvar_read(colvar%reaction_path_param%colvar_p(i)%colvar, i, colvar_subsection, para_env)
519               ENDDO
520            ELSE
521               CPABORT("CV REACTION PATH: the number of CV to define the path must be >0 ")
522            ENDIF
523            colvar%reaction_path_param%n_components = ncol
524            NULLIFY (range)
525            CALL section_vals_val_get(path_section, "RANGE", r_vals=range)
526            CALL section_vals_val_get(path_section, "STEP_SIZE", r_val=colvar%reaction_path_param%step_size)
527            iend = CEILING(MAX(RANGE(1), RANGE(2))/colvar%reaction_path_param%step_size)
528            istart = FLOOR(MIN(RANGE(1), RANGE(2))/colvar%reaction_path_param%step_size)
529            colvar%reaction_path_param%function_bounds(1) = istart
530            colvar%reaction_path_param%function_bounds(2) = iend
531            colvar%reaction_path_param%nr_frames = 2 !iend - istart + 1
532            ALLOCATE (colvar%reaction_path_param%f_vals(ncol, istart:iend))
533            CALL section_vals_val_get(path_section, "VARIABLE", c_vals=my_par, i_rep_val=1)
534            CALL section_vals_val_get(path_section, "FUNCTION", n_rep_val=ncol)
535            check = (ncol == SIZE(colvar%reaction_path_param%colvar_p))
536            CPASSERT(check)
537            CALL initf(ncol)
538            DO i = 1, ncol
539               CALL section_vals_val_get(path_section, "FUNCTION", c_val=path_function, i_rep_val=i)
540               CALL compress(path_function, full=.TRUE.)
541               CALL parsef(i, TRIM(path_function), my_par)
542               DO j = istart, iend
543                  my_val = REAL(j, kind=dp)*colvar%reaction_path_param%step_size
544                  colvar%reaction_path_param%f_vals(i, j) = evalf(i, my_val)
545               END DO
546            END DO
547            CALL finalizef()
548
549            iw1 = cp_print_key_unit_nr(logger, path_section, &
550                                       "MAP", middle_name=fmid, extension=".dat", file_status="REPLACE")
551            IF (iw1 > 0) THEN
552               CALL section_vals_val_get(path_section, "MAP%GRID_SPACING", n_rep_val=ncol)
553               ALLOCATE (grid_sp(ncol))
554               DO i = 1, ncol
555                  CALL section_vals_val_get(path_section, "MAP%GRID_SPACING", r_val=grid_sp(i))
556               END DO
557               CALL section_vals_val_get(path_section, "MAP%RANGE", n_rep_val=ncol)
558               CPASSERT(ncol == SIZE(grid_sp))
559               ALLOCATE (p_range(2, ncol))
560               ALLOCATE (p_bounds(2, ncol))
561               DO i = 1, ncol
562                  CALL section_vals_val_get(path_section, "MAP%RANGE", r_vals=g_range)
563                  p_range(:, i) = g_range(:)
564                  p_bounds(2, i) = CEILING(MAX(p_range(1, i), p_range(2, i))/grid_sp(i))
565                  p_bounds(1, i) = FLOOR(MIN(p_range(1, i), p_range(2, i))/grid_sp(i))
566               END DO
567               ALLOCATE (s1v(2, istart:iend))
568               ALLOCATE (s1(2))
569               ALLOCATE (grid_point(ncol))
570               v_count = 0
571               kk = rec_eval_grid(iw1, ncol, colvar%reaction_path_param%f_vals, v_count, &
572                                  grid_point, grid_sp, colvar%reaction_path_param%step_size, istart, &
573                                  iend, s1v, s1, p_bounds, colvar%reaction_path_param%lambda, ifunc=ifunc, &
574                                  nconf=colvar%reaction_path_param%nr_frames)
575               DEALLOCATE (grid_sp)
576               DEALLOCATE (p_range)
577               DEALLOCATE (p_bounds)
578               DEALLOCATE (s1v)
579               DEALLOCATE (s1)
580               DEALLOCATE (grid_point)
581            END IF
582            CALL cp_print_key_finished_output(iw1, logger, path_section, &
583                                              "MAP")
584         END IF
585
586      ELSE IF (my_subsection(11)) THEN
587         ! combine colvar
588         CALL colvar_create(colvar, combine_colvar_id)
589         colvar%use_points = .FALSE.
590         colvar_subsection => section_vals_get_subs_vals(combine_section, "COLVAR")
591         CALL section_vals_get(colvar_subsection, n_repetition=ncol)
592         ALLOCATE (colvar%combine_cvs_param%colvar_p(ncol))
593         ! In case we need to print some information..
594         iw = cp_print_key_unit_nr(logger, colvar_section, &
595                                   "PRINT%PROGRAM_RUN_INFO", extension=".colvarLog")
596         IF (iw > 0) THEN
597            WRITE (iw, '( A )') '          '// &
598               '**********************************************************************'
599            WRITE (iw, '( A,I8)') ' COLVARS| COLVAR INPUT INDEX: ', icol
600            WRITE (iw, '( A,T49,4I8)') ' COLVARS| COMBINATION OF THE FOLLOWING COLVARS:'
601         END IF
602         CALL cp_print_key_finished_output(iw, logger, colvar_section, &
603                                           "PRINT%PROGRAM_RUN_INFO")
604         ! Parsing the real COLVARs
605         DO i = 1, ncol
606            NULLIFY (colvar%combine_cvs_param%colvar_p(i)%colvar)
607            CALL colvar_read(colvar%combine_cvs_param%colvar_p(i)%colvar, i, colvar_subsection, para_env)
608         END DO
609         ! Function definition
610         CALL section_vals_val_get(combine_section, "FUNCTION", c_val=colvar%combine_cvs_param%function)
611         CALL compress(colvar%combine_cvs_param%function, full=.TRUE.)
612         ! Variables
613         CALL section_vals_val_get(combine_section, "VARIABLES", c_vals=my_par)
614         ALLOCATE (colvar%combine_cvs_param%variables(SIZE(my_par)))
615         colvar%combine_cvs_param%variables = my_par
616         ! Check that the number of COLVAR provided is equal to the number of variables..
617         IF (SIZE(my_par) /= ncol) &
618            CALL cp_abort(__LOCATION__, &
619                          "Number of defined COLVAR for COMBINE_COLVAR is different from the "// &
620                          "number of variables! It is not possible to define COLVARs in a COMBINE_COLVAR "// &
621                          "and avoid their usage in the combininig function!")
622         ! Parameters
623         ALLOCATE (colvar%combine_cvs_param%c_parameters(0))
624         CALL section_vals_val_get(combine_section, "PARAMETERS", n_rep_val=ncol)
625         DO i = 1, ncol
626            isize = SIZE(colvar%combine_cvs_param%c_parameters)
627            CALL section_vals_val_get(combine_section, "PARAMETERS", c_vals=my_par, i_rep_val=i)
628            CALL reallocate(colvar%combine_cvs_param%c_parameters, 1, isize + SIZE(my_par))
629            colvar%combine_cvs_param%c_parameters(isize + 1:isize + SIZE(my_par)) = my_par
630         END DO
631         ALLOCATE (colvar%combine_cvs_param%v_parameters(0))
632         CALL section_vals_val_get(combine_section, "VALUES", n_rep_val=ncol)
633         DO i = 1, ncol
634            isize = SIZE(colvar%combine_cvs_param%v_parameters)
635            CALL section_vals_val_get(combine_section, "VALUES", r_vals=my_vals, i_rep_val=i)
636            CALL reallocate(colvar%combine_cvs_param%v_parameters, 1, isize + SIZE(my_vals))
637            colvar%combine_cvs_param%v_parameters(isize + 1:isize + SIZE(my_vals)) = my_vals
638         END DO
639         ! Info on derivative evaluation
640         CALL section_vals_val_get(combine_section, "DX", r_val=colvar%combine_cvs_param%dx)
641         CALL section_vals_val_get(combine_section, "ERROR_LIMIT", r_val=colvar%combine_cvs_param%lerr)
642      ELSE IF (my_subsection(12)) THEN
643         ! Population
644         wrk_section => population_section
645         CALL colvar_create(colvar, population_colvar_id)
646         CALL colvar_check_points(colvar, population_section)
647
648         NULLIFY (colvar%population_param%i_at_from, colvar%population_param%c_kinds_from)
649         NULLIFY (colvar%population_param%i_at_to, colvar%population_param%c_kinds_to)
650         ! This section can be repeated
651
652         CALL section_vals_val_get(population_section, "ATOMS_FROM", n_rep_val=n_var)
653         ndim = 0
654         IF (n_var /= 0) THEN
655            ! INDEX LIST
656            DO k = 1, n_var
657               CALL section_vals_val_get(population_section, "ATOMS_FROM", i_rep_val=k, i_vals=iatms)
658               CALL reallocate(colvar%population_param%i_at_from, 1, ndim + SIZE(iatms))
659               colvar%population_param%i_at_from(ndim + 1:ndim + SIZE(iatms)) = iatms
660               ndim = ndim + SIZE(iatms)
661            END DO
662            colvar%population_param%n_atoms_from = ndim
663            colvar%population_param%use_kinds_from = .FALSE.
664         ELSE
665            ! KINDS
666            CALL section_vals_val_get(population_section, "KINDS_FROM", n_rep_val=n_var)
667            CPASSERT(n_var > 0)
668            DO k = 1, n_var
669               CALL section_vals_val_get(population_section, "KINDS_FROM", i_rep_val=k, c_vals=c_kinds)
670               CALL reallocate(colvar%population_param%c_kinds_from, 1, ndim + SIZE(c_kinds))
671               colvar%population_param%c_kinds_from(ndim + 1:ndim + SIZE(c_kinds)) = c_kinds
672               ndim = ndim + SIZE(c_kinds)
673            END DO
674            colvar%population_param%n_atoms_from = 0
675            colvar%population_param%use_kinds_from = .TRUE.
676            ! Uppercase the label
677            DO k = 1, ndim
678               CALL uppercase(colvar%population_param%c_kinds_from(k))
679            END DO
680         END IF
681         ! This section can be repeated
682         CALL section_vals_val_get(population_section, "ATOMS_TO", n_rep_val=n_var)
683         ndim = 0
684         IF (n_var /= 0) THEN
685            ! INDEX LIST
686            DO k = 1, n_var
687               CALL section_vals_val_get(population_section, "ATOMS_TO", i_rep_val=k, i_vals=iatms)
688               CALL reallocate(colvar%population_param%i_at_to, 1, ndim + SIZE(iatms))
689               colvar%population_param%i_at_to(ndim + 1:ndim + SIZE(iatms)) = iatms
690               ndim = ndim + SIZE(iatms)
691            END DO
692            colvar%population_param%n_atoms_to = ndim
693            colvar%population_param%use_kinds_to = .FALSE.
694         ELSE
695            ! KINDS
696            CALL section_vals_val_get(population_section, "KINDS_TO", n_rep_val=n_var)
697            CPASSERT(n_var > 0)
698            DO k = 1, n_var
699               CALL section_vals_val_get(population_section, "KINDS_TO", i_rep_val=k, c_vals=c_kinds)
700               CALL reallocate(colvar%population_param%c_kinds_to, 1, ndim + SIZE(c_kinds))
701               colvar%population_param%c_kinds_to(ndim + 1:ndim + SIZE(c_kinds)) = c_kinds
702               ndim = ndim + SIZE(c_kinds)
703            END DO
704            colvar%population_param%n_atoms_to = 0
705            colvar%population_param%use_kinds_to = .TRUE.
706            ! Uppercase the label
707            DO k = 1, ndim
708               CALL uppercase(colvar%population_param%c_kinds_to(k))
709            END DO
710         END IF
711         ! Let's finish reading the other parameters
712         CALL section_vals_val_get(population_section, "R0", r_val=colvar%population_param%r_0)
713         CALL section_vals_val_get(population_section, "NN", i_val=colvar%population_param%nncrd)
714         CALL section_vals_val_get(population_section, "ND", i_val=colvar%population_param%ndcrd)
715         CALL section_vals_val_get(population_section, "N0", i_val=colvar%population_param%n0)
716         CALL section_vals_val_get(population_section, "SIGMA", r_val=colvar%population_param%sigma)
717      ELSE IF (my_subsection(13)) THEN
718         ! Angle between two planes
719         wrk_section => plane_plane_angle_section
720         CALL colvar_create(colvar, plane_plane_angle_colvar_id)
721         CALL colvar_check_points(colvar, plane_plane_angle_section)
722         ! Read the specification of the two planes
723         plane_sections => section_vals_get_subs_vals(plane_plane_angle_section, "PLANE")
724         CALL section_vals_get(plane_sections, n_repetition=n_var)
725         IF (n_var /= 2) &
726            CPABORT("PLANE_PLANE_ANGLE Colvar section: Two PLANE sections must be provided!")
727         ! Plane 1
728         CALL section_vals_val_get(plane_sections, "DEF_TYPE", i_rep_section=1, &
729                                   i_val=colvar%plane_plane_angle_param%plane1%type_of_def)
730         IF (colvar%plane_plane_angle_param%plane1%type_of_def == plane_def_vec) THEN
731            CALL section_vals_val_get(plane_sections, "NORMAL_VECTOR", i_rep_section=1, &
732                                      r_vals=s1)
733            colvar%plane_plane_angle_param%plane1%normal_vec = s1
734         ELSE
735            CALL section_vals_val_get(plane_sections, "ATOMS", i_rep_section=1, &
736                                      i_vals=iatms)
737            colvar%plane_plane_angle_param%plane1%points = iatms
738         END IF
739
740         ! Plane 2
741         CALL section_vals_val_get(plane_sections, "DEF_TYPE", i_rep_section=2, &
742                                   i_val=colvar%plane_plane_angle_param%plane2%type_of_def)
743         IF (colvar%plane_plane_angle_param%plane2%type_of_def == plane_def_vec) THEN
744            CALL section_vals_val_get(plane_sections, "NORMAL_VECTOR", i_rep_section=2, &
745                                      r_vals=s1)
746            colvar%plane_plane_angle_param%plane2%normal_vec = s1
747         ELSE
748            CALL section_vals_val_get(plane_sections, "ATOMS", i_rep_section=2, &
749                                      i_vals=iatms)
750            colvar%plane_plane_angle_param%plane2%points = iatms
751         END IF
752      ELSE IF (my_subsection(14)) THEN
753         ! Gyration Radius
754         wrk_section => gyration_section
755         CALL colvar_create(colvar, gyration_colvar_id)
756         CALL colvar_check_points(colvar, gyration_section)
757
758         NULLIFY (colvar%gyration_param%i_at, colvar%gyration_param%c_kinds)
759
760         ! This section can be repeated
761         CALL section_vals_val_get(gyration_section, "ATOMS", n_rep_val=n_var)
762         ndim = 0
763         IF (n_var /= 0) THEN
764            ! INDEX LIST
765            DO k = 1, n_var
766               CALL section_vals_val_get(gyration_section, "ATOMS", i_rep_val=k, i_vals=iatms)
767               CALL reallocate(colvar%gyration_param%i_at, 1, ndim + SIZE(iatms))
768               colvar%gyration_param%i_at(ndim + 1:ndim + SIZE(iatms)) = iatms
769               ndim = ndim + SIZE(iatms)
770            END DO
771            colvar%gyration_param%n_atoms = ndim
772            colvar%gyration_param%use_kinds = .FALSE.
773         ELSE
774            ! KINDS
775            CALL section_vals_val_get(gyration_section, "KINDS", n_rep_val=n_var)
776            CPASSERT(n_var > 0)
777            DO k = 1, n_var
778               CALL section_vals_val_get(gyration_section, "KINDS", i_rep_val=k, c_vals=c_kinds)
779               CALL reallocate(colvar%gyration_param%c_kinds, 1, ndim + SIZE(c_kinds))
780               colvar%gyration_param%c_kinds(ndim + 1:ndim + SIZE(c_kinds)) = c_kinds
781               ndim = ndim + SIZE(c_kinds)
782            END DO
783            colvar%gyration_param%n_atoms = 0
784            colvar%gyration_param%use_kinds = .TRUE.
785            ! Uppercase the label
786            DO k = 1, ndim
787               CALL uppercase(colvar%gyration_param%c_kinds(k))
788            END DO
789         END IF
790      ELSE IF (my_subsection(15)) THEN
791         ! RMSD_AB
792         wrk_section => rmsd_section
793         CALL colvar_create(colvar, rmsd_colvar_id)
794
795         NULLIFY (colvar%rmsd_param%i_rmsd, colvar%rmsd_param%r_ref, colvar%rmsd_param%weights)
796
797         frame_section => section_vals_get_subs_vals(rmsd_section, "FRAME")
798         CALL section_vals_get(frame_section, n_repetition=nr_frame)
799
800         colvar%rmsd_param%nr_frames = nr_frame
801         ! Calculation is aborted if reference frame are less than 2
802         CPASSERT(nr_frame >= 1 .AND. nr_frame <= 2)
803         CALL read_frames(frame_section, para_env, nr_frame, colvar%rmsd_param%r_ref, &
804                          colvar%rmsd_param%n_atoms)
805
806         ALLOCATE (colvar%rmsd_param%weights(colvar%rmsd_param%n_atoms))
807         colvar%rmsd_param%weights = 0.0_dp
808
809         CALL section_vals_val_get(rmsd_section, "SUBSET_TYPE", i_val=colvar%rmsd_param%subset)
810         IF (colvar%rmsd_param%subset == rmsd_all) THEN
811            ALLOCATE (colvar%rmsd_param%i_rmsd(colvar%rmsd_param%n_atoms))
812            DO i = 1, colvar%rmsd_param%n_atoms
813               colvar%rmsd_param%i_rmsd(i) = i
814            END DO
815         ELSE IF (colvar%rmsd_param%subset == rmsd_list) THEN
816            ! This section can be repeated
817            CALL section_vals_val_get(rmsd_section, "ATOMS", n_rep_val=n_var)
818            ndim = 0
819            IF (n_var /= 0) THEN
820               ! INDEX LIST
821               DO k = 1, n_var
822                  CALL section_vals_val_get(rmsd_section, "ATOMS", i_rep_val=k, i_vals=iatms)
823                  CALL reallocate(colvar%rmsd_param%i_rmsd, 1, ndim + SIZE(iatms))
824                  colvar%rmsd_param%i_rmsd(ndim + 1:ndim + SIZE(iatms)) = iatms
825                  ndim = ndim + SIZE(iatms)
826               END DO
827               colvar%rmsd_param%n_atoms = ndim
828            ELSE
829               CPABORT("CV RMSD: if SUBSET_TYPE=LIST a list of atoms needs to be provided ")
830            END IF
831         ELSE IF (colvar%rmsd_param%subset == rmsd_weightlist) THEN
832            CALL section_vals_val_get(rmsd_section, "ATOMS", n_rep_val=n_var)
833            ndim = 0
834            IF (n_var /= 0) THEN
835               ! INDEX LIST
836               DO k = 1, n_var
837                  CALL section_vals_val_get(rmsd_section, "ATOMS", i_rep_val=k, i_vals=iatms)
838                  CALL reallocate(colvar%rmsd_param%i_rmsd, 1, ndim + SIZE(iatms))
839                  colvar%rmsd_param%i_rmsd(ndim + 1:ndim + SIZE(iatms)) = iatms
840                  ndim = ndim + SIZE(iatms)
841               END DO
842               colvar%rmsd_param%n_atoms = ndim
843            ELSE
844               CPABORT("CV RMSD: if SUBSET_TYPE=WEIGHT_LIST a list of atoms needs to be provided ")
845            END IF
846            CALL section_vals_val_get(rmsd_section, "WEIGHTS", n_rep_val=n_var)
847            ndim = 0
848            IF (n_var /= 0) THEN
849               ! INDEX LIST
850               DO k = 1, n_var
851                  CALL section_vals_val_get(rmsd_section, "WEIGHTS", i_rep_val=k, r_vals=wei)
852                  CALL reallocate(weights, 1, ndim + SIZE(wei))
853                  weights(ndim + 1:ndim + SIZE(wei)) = wei
854                  ndim = ndim + SIZE(wei)
855               END DO
856               IF (ndim /= colvar%rmsd_param%n_atoms) &
857                  CALL cp_abort(__LOCATION__, "CV RMSD: list of atoms and list of "// &
858                                "weights need to contain same number of entries. ")
859               DO i = 1, ndim
860                  ii = colvar%rmsd_param%i_rmsd(i)
861                  colvar%rmsd_param%weights(ii) = weights(i)
862               END DO
863               DEALLOCATE (weights)
864            ELSE
865               CPABORT("CV RMSD: if SUBSET_TYPE=WEIGHT_LIST a list of weights need to be provided. ")
866            END IF
867
868         ELSE
869            CPABORT("CV RMSD: unknown SUBSET_TYPE.")
870         END IF
871
872         CALL section_vals_val_get(rmsd_section, "ALIGN_FRAMES", l_val=colvar%rmsd_param%align_frames)
873      ELSE IF (my_subsection(17)) THEN
874         ! Work on XYZ positions of atoms
875         wrk_section => xyz_diag_section
876         CALL colvar_create(colvar, xyz_diag_colvar_id)
877         CALL colvar_check_points(colvar, wrk_section)
878         CALL section_vals_val_get(wrk_section, "ATOM", i_val=iatm)
879         CALL section_vals_val_get(wrk_section, "COMPONENT", i_val=icomponent)
880         CALL section_vals_val_get(wrk_section, "PBC", l_val=colvar%xyz_diag_param%use_pbc)
881         CALL section_vals_val_get(wrk_section, "ABSOLUTE_POSITION", l_val=colvar%xyz_diag_param%use_absolute_position)
882         colvar%xyz_diag_param%i_atom = iatm
883         colvar%xyz_diag_param%component = icomponent
884      ELSE IF (my_subsection(18)) THEN
885         ! Work on the outer diagonal (two atoms A,B) XYZ positions
886         wrk_section => xyz_outerdiag_section
887         CALL colvar_create(colvar, xyz_outerdiag_colvar_id)
888         CALL colvar_check_points(colvar, wrk_section)
889         CALL section_vals_val_get(wrk_section, "ATOMS", i_vals=iatms)
890         colvar%xyz_outerdiag_param%i_atoms = iatms
891         CALL section_vals_val_get(wrk_section, "COMPONENT_A", i_val=icomponent)
892         colvar%xyz_outerdiag_param%components(1) = icomponent
893         CALL section_vals_val_get(wrk_section, "COMPONENT_B", i_val=icomponent)
894         colvar%xyz_outerdiag_param%components(2) = icomponent
895         CALL section_vals_val_get(wrk_section, "PBC", l_val=colvar%xyz_outerdiag_param%use_pbc)
896      ELSE IF (my_subsection(19)) THEN
897         ! Energy
898         wrk_section => u_section
899         CALL colvar_create(colvar, u_colvar_id)
900         colvar%u_param%mixed_energy_section => section_vals_get_subs_vals(wrk_section, "MIXED")
901         CALL section_vals_get(colvar%u_param%mixed_energy_section, explicit=use_mixed_energy)
902         IF (.NOT. use_mixed_energy) NULLIFY (colvar%u_param%mixed_energy_section)
903      ELSE IF (my_subsection(20)) THEN
904         ! Wc hydrogen bond
905         wrk_section => Wc_section
906         CALL colvar_create(colvar, Wc_colvar_id)
907         CALL colvar_check_points(colvar, Wc_section)
908         CALL section_vals_val_get(Wc_section, "ATOMS", i_vals=iatms)
909         CALL section_vals_val_get(wrk_section, "RCUT", r_val=my_val(1))
910         colvar%Wc%rcut = cp_unit_to_cp2k(my_val(1), "angstrom")
911         colvar%Wc%ids = iatms
912      ELSE IF (my_subsection(21)) THEN
913         ! HBP colvar
914         wrk_section => HBP_section
915         CALL colvar_create(colvar, HBP_colvar_id)
916         CALL colvar_check_points(colvar, HBP_section)
917         CALL section_vals_val_get(wrk_section, "NPOINTS", i_val=colvar%HBP%nPoints)
918         CALL section_vals_val_get(wrk_section, "RCUT", r_val=my_val(1))
919         colvar%HBP%rcut = cp_unit_to_cp2k(my_val(1), "angstrom")
920         CALL section_vals_val_get(wrk_section, "RCUT", r_val=colvar%HBP%shift)
921
922         ALLOCATE (colvar%HBP%ids(colvar%HBP%nPoints, 3))
923         ALLOCATE (colvar%HBP%ewc(colvar%HBP%nPoints))
924         DO i = 1, colvar%HBP%nPoints
925            CALL section_vals_val_get(wrk_section, "ATOMS", i_rep_val=i, i_vals=iatms)
926            colvar%HBP%ids(i, :) = iatms
927         ENDDO
928      ELSE IF (my_subsection(22)) THEN
929         ! Ring Puckering
930         CALL colvar_create(colvar, ring_puckering_colvar_id)
931         CALL section_vals_val_get(ring_puckering_section, "ATOMS", i_vals=iatms)
932         colvar%ring_puckering_param%nring = SIZE(iatms)
933         ALLOCATE (colvar%ring_puckering_param%atoms(SIZE(iatms)))
934         colvar%ring_puckering_param%atoms = iatms
935         CALL section_vals_val_get(ring_puckering_section, "COORDINATE", &
936                                   i_val=colvar%ring_puckering_param%iq)
937         ! test the validity of the parameters
938         ndim = colvar%ring_puckering_param%nring
939         IF (ndim <= 3) &
940            CPABORT("CV Ring Puckering: Ring size has to be 4 or larger. ")
941         ii = colvar%ring_puckering_param%iq
942         IF (ABS(ii) == 1 .OR. ii < -(ndim - 1)/2 .OR. ii > ndim/2) &
943            CPABORT("CV Ring Puckering: Invalid coordinate number.")
944      ELSE IF (my_subsection(23)) THEN
945         ! Minimum Distance
946         wrk_section => mindist_section
947         CALL colvar_create(colvar, mindist_colvar_id)
948         CALL colvar_check_points(colvar, mindist_section)
949         NULLIFY (colvar%mindist_param%i_dist_from, colvar%mindist_param%i_coord_from, &
950                  colvar%mindist_param%k_coord_from, colvar%mindist_param%i_coord_to, &
951                  colvar%mindist_param%k_coord_to)
952         CALL section_vals_val_get(mindist_section, "ATOMS_DISTANCE", i_vals=iatms)
953         colvar%mindist_param%n_dist_from = SIZE(iatms)
954         ALLOCATE (colvar%mindist_param%i_dist_from(SIZE(iatms)))
955         colvar%mindist_param%i_dist_from = iatms
956         CALL section_vals_val_get(mindist_section, "ATOMS_FROM", n_rep_val=n_var)
957         ndim = 0
958         IF (n_var /= 0) THEN
959            ! INDEX LIST
960            DO k = 1, n_var
961               CALL section_vals_val_get(mindist_section, "ATOMS_FROM", i_rep_val=k, i_vals=iatms)
962               CALL reallocate(colvar%mindist_param%i_coord_from, 1, ndim + SIZE(iatms))
963               colvar%mindist_param%i_coord_from(ndim + 1:ndim + SIZE(iatms)) = iatms
964               ndim = ndim + SIZE(iatms)
965            END DO
966            colvar%mindist_param%n_coord_from = ndim
967            colvar%mindist_param%use_kinds_from = .FALSE.
968         ELSE
969            !KINDS
970            CALL section_vals_val_get(mindist_section, "KINDS_FROM", n_rep_val=n_var)
971            CPASSERT(n_var > 0)
972            DO k = 1, n_var
973               CALL section_vals_val_get(mindist_section, "KINDS_FROM", i_rep_val=k, c_vals=c_kinds)
974               CALL reallocate(colvar%mindist_param%k_coord_from, 1, ndim + SIZE(c_kinds))
975               colvar%mindist_param%k_coord_from(ndim + 1:ndim + SIZE(c_kinds)) = c_kinds
976               ndim = ndim + SIZE(c_kinds)
977            END DO
978            colvar%mindist_param%n_coord_from = 0
979            colvar%mindist_param%use_kinds_from = .TRUE.
980            ! Uppercase the label
981            DO k = 1, ndim
982               CALL uppercase(colvar%mindist_param%k_coord_from(k))
983            END DO
984         END IF
985
986         CALL section_vals_val_get(mindist_section, "ATOMS_TO", n_rep_val=n_var)
987         ndim = 0
988         IF (n_var /= 0) THEN
989            ! INDEX LIST
990            DO k = 1, n_var
991               CALL section_vals_val_get(mindist_section, "ATOMS_TO", i_rep_val=k, i_vals=iatms)
992               CALL reallocate(colvar%mindist_param%i_coord_to, 1, ndim + SIZE(iatms))
993               colvar%mindist_param%i_coord_to(ndim + 1:ndim + SIZE(iatms)) = iatms
994               ndim = ndim + SIZE(iatms)
995            END DO
996            colvar%mindist_param%n_coord_to = ndim
997            colvar%mindist_param%use_kinds_to = .FALSE.
998         ELSE
999            !KINDS
1000            CALL section_vals_val_get(mindist_section, "KINDS_TO", n_rep_val=n_var)
1001            CPASSERT(n_var > 0)
1002            DO k = 1, n_var
1003               CALL section_vals_val_get(mindist_section, "KINDS_TO", i_rep_val=k, c_vals=c_kinds)
1004               CALL reallocate(colvar%mindist_param%k_coord_to, 1, ndim + SIZE(c_kinds))
1005               colvar%mindist_param%k_coord_to(ndim + 1:ndim + SIZE(c_kinds)) = c_kinds
1006               ndim = ndim + SIZE(c_kinds)
1007            END DO
1008            colvar%mindist_param%n_coord_to = 0
1009            colvar%mindist_param%use_kinds_to = .TRUE.
1010            ! Uppercase the label
1011            DO k = 1, ndim
1012               CALL uppercase(colvar%mindist_param%k_coord_to(k))
1013            END DO
1014         END IF
1015
1016         CALL section_vals_val_get(mindist_section, "R0", r_val=colvar%mindist_param%r_cut)
1017         CALL section_vals_val_get(mindist_section, "NN", i_val=colvar%mindist_param%p_exp)
1018         CALL section_vals_val_get(mindist_section, "ND", i_val=colvar%mindist_param%q_exp)
1019!       CALL section_vals_val_get(mindist_section,"NC",r_val=colvar%mindist_param%n_cut)
1020         CALL section_vals_val_get(mindist_section, "LAMBDA", r_val=colvar%mindist_param%lambda)
1021      ELSE IF (my_subsection(24)) THEN
1022         ! Distance carboxylic acid and hydronium
1023         CALL colvar_create(colvar, acid_hyd_dist_colvar_id)
1024         NULLIFY (colvar%acid_hyd_dist_param%i_oxygens_water)
1025         NULLIFY (colvar%acid_hyd_dist_param%i_oxygens_acid)
1026         NULLIFY (colvar%acid_hyd_dist_param%i_hydrogens)
1027         CALL read_acid_hydronium_colvars(acid_hyd_dist_section, colvar, acid_hyd_dist_colvar_id, &
1028                                          colvar%acid_hyd_dist_param%n_oxygens_water, &
1029                                          colvar%acid_hyd_dist_param%n_oxygens_acid, &
1030                                          colvar%acid_hyd_dist_param%n_hydrogens, &
1031                                          colvar%acid_hyd_dist_param%i_oxygens_water, &
1032                                          colvar%acid_hyd_dist_param%i_oxygens_acid, &
1033                                          colvar%acid_hyd_dist_param%i_hydrogens)
1034      ELSE IF (my_subsection(25)) THEN
1035         ! Number of oxygens in 1st shell of hydronium for carboxylic acid / water system
1036         CALL colvar_create(colvar, acid_hyd_shell_colvar_id)
1037         NULLIFY (colvar%acid_hyd_shell_param%i_oxygens_water)
1038         NULLIFY (colvar%acid_hyd_shell_param%i_oxygens_acid)
1039         NULLIFY (colvar%acid_hyd_shell_param%i_hydrogens)
1040         CALL read_acid_hydronium_colvars(acid_hyd_shell_section, colvar, acid_hyd_shell_colvar_id, &
1041                                          colvar%acid_hyd_shell_param%n_oxygens_water, &
1042                                          colvar%acid_hyd_shell_param%n_oxygens_acid, &
1043                                          colvar%acid_hyd_shell_param%n_hydrogens, &
1044                                          colvar%acid_hyd_shell_param%i_oxygens_water, &
1045                                          colvar%acid_hyd_shell_param%i_oxygens_acid, &
1046                                          colvar%acid_hyd_shell_param%i_hydrogens)
1047      ELSE IF (my_subsection(26)) THEN
1048         ! Distance hydronium and hydroxide, autoionization of water
1049         CALL colvar_create(colvar, hydronium_dist_colvar_id)
1050         NULLIFY (colvar%hydronium_dist_param%i_oxygens)
1051         NULLIFY (colvar%hydronium_dist_param%i_hydrogens)
1052         CALL read_hydronium_colvars(hydronium_dist_section, colvar, hydronium_dist_colvar_id, &
1053                                     colvar%hydronium_dist_param%n_oxygens, &
1054                                     colvar%hydronium_dist_param%n_hydrogens, &
1055                                     colvar%hydronium_dist_param%i_oxygens, &
1056                                     colvar%hydronium_dist_param%i_hydrogens)
1057      END IF
1058      CALL colvar_setup(colvar)
1059
1060      iw = cp_print_key_unit_nr(logger, colvar_section, &
1061                                "PRINT%PROGRAM_RUN_INFO", extension=".colvarLog")
1062      IF (iw > 0) THEN
1063         tag = "ATOMS: "
1064         IF (colvar%use_points) tag = "POINTS:"
1065         ! Description header
1066         IF (colvar%type_id /= combine_colvar_id) THEN
1067            WRITE (iw, '( A )') '          '// &
1068               '----------------------------------------------------------------------'
1069            WRITE (iw, '( A,I8)') ' COLVARS| COLVAR INPUT INDEX: ', icol
1070         END IF
1071         ! Colvar Description
1072         SELECT CASE (colvar%type_id)
1073         CASE (angle_colvar_id)
1074            WRITE (iw, '( A,T57,3I8)') ' COLVARS| ANGLE          >>> '//tag, &
1075               colvar%angle_param%i_at_angle
1076         CASE (dfunct_colvar_id)
1077            WRITE (iw, '( A,T49,4I8)') ' COLVARS| DISTANCE DIFFERENCE  >>> '//tag, &
1078               colvar%dfunct_param%i_at_dfunct
1079         CASE (plane_distance_colvar_id)
1080            WRITE (iw, '( A,T57,3I8)') ' COLVARS| PLANE DISTANCE - PLANE  >>> '//tag, &
1081               colvar%plane_distance_param%plane
1082            WRITE (iw, '( A,T73,1I8)') ' COLVARS| PLANE DISTANCE - POINT  >>> '//tag, &
1083               colvar%plane_distance_param%point
1084         CASE (plane_plane_angle_colvar_id)
1085            IF (colvar%plane_plane_angle_param%plane1%type_of_def == plane_def_atoms) THEN
1086               WRITE (iw, '( A,T57,3I8)') ' COLVARS| PLANE-PLANE ANGLE - PLANE 1  (ATOMS) >>> '//tag, &
1087                  colvar%plane_plane_angle_param%plane1%points
1088            ELSE
1089               WRITE (iw, '( A,T57,3F8.3)') ' COLVARS| PLANE-PLANE ANGLE - PLANE 1 (VECTOR) >>> '//tag, &
1090                  colvar%plane_plane_angle_param%plane1%normal_vec
1091            END IF
1092
1093            IF (colvar%plane_plane_angle_param%plane2%type_of_def == plane_def_atoms) THEN
1094               WRITE (iw, '( A,T57,3I8)') ' COLVARS| PLANE-PLANE ANGLE - PLANE 1  (ATOMS) >>> '//tag, &
1095                  colvar%plane_plane_angle_param%plane2%points
1096            ELSE
1097               WRITE (iw, '( A,T57,3F8.3)') ' COLVARS| PLANE-PLANE ANGLE - PLANE 1 (VECTOR) >>> '//tag, &
1098                  colvar%plane_plane_angle_param%plane2%normal_vec
1099            END IF
1100         CASE (torsion_colvar_id)
1101            WRITE (iw, '( A,T49,4I8)') ' COLVARS| TORSION       >>> '//tag, &
1102               colvar%torsion_param%i_at_tors
1103         CASE (dist_colvar_id)
1104            WRITE (iw, '( A,T65,2I8)') ' COLVARS| BOND          >>> '//tag, &
1105               colvar%dist_param%i_at, colvar%dist_param%j_at
1106         CASE (coord_colvar_id)
1107            IF (colvar%coord_param%do_chain) THEN
1108               WRITE (iw, '( A)') ' COLVARS| COORDINATION CHAIN FC(from->to)*FC(to->to_B)>> '
1109            END IF
1110            IF (colvar%coord_param%use_kinds_from) THEN
1111               WRITE (iw, '( A,T71,A10)') (' COLVARS| COORDINATION  >>> FROM KINDS', &
1112                                           ADJUSTR(colvar%coord_param%c_kinds_from(kk) (1:10)), &
1113                                           kk=1, SIZE(colvar%coord_param%c_kinds_from))
1114            ELSE
1115               WRITE (iw, '( A,T71,I10)') (' COLVARS| COORDINATION  >>> FROM '//tag, &
1116                                           colvar%coord_param%i_at_from(kk), &
1117                                           kk=1, SIZE(colvar%coord_param%i_at_from))
1118            END IF
1119            IF (colvar%coord_param%use_kinds_to) THEN
1120               WRITE (iw, '( A,T71,A10)') (' COLVARS| COORDINATION  >>>   TO KINDS', &
1121                                           ADJUSTR(colvar%coord_param%c_kinds_to(kk) (1:10)), &
1122                                           kk=1, SIZE(colvar%coord_param%c_kinds_to))
1123            ELSE
1124               WRITE (iw, '( A,T71,I10)') (' COLVARS| COORDINATION  >>>   TO '//tag, &
1125                                           colvar%coord_param%i_at_to(kk), &
1126                                           kk=1, SIZE(colvar%coord_param%i_at_to))
1127            END IF
1128            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| R0', colvar%coord_param%r_0
1129            WRITE (iw, '( A,T71,I10)') ' COLVARS| NN', colvar%coord_param%nncrd
1130            WRITE (iw, '( A,T71,I10)') ' COLVARS| ND', colvar%coord_param%ndcrd
1131            IF (colvar%coord_param%do_chain) THEN
1132               IF (colvar%coord_param%use_kinds_to_b) THEN
1133                  WRITE (iw, '( A,T71,A10)') (' COLVARS| COORDINATION  >>>   TO KINDS B', &
1134                                              ADJUSTR(colvar%coord_param%c_kinds_to_b(kk) (1:10)), &
1135                                              kk=1, SIZE(colvar%coord_param%c_kinds_to_b))
1136               ELSE
1137                  WRITE (iw, '( A,T71,I10)') (' COLVARS| COORDINATION  >>>   TO '//tag//' B', &
1138                                              colvar%coord_param%i_at_to_b(kk), &
1139                                              kk=1, SIZE(colvar%coord_param%i_at_to_b))
1140               END IF
1141               WRITE (iw, '( A,T71,F10.5)') ' COLVARS| R0 B', colvar%coord_param%r_0_b
1142               WRITE (iw, '( A,T71,I10)') ' COLVARS| NN B', colvar%coord_param%nncrd_b
1143               WRITE (iw, '( A,T71,I10)') ' COLVARS| ND B', colvar%coord_param%ndcrd_b
1144            END IF
1145         CASE (population_colvar_id)
1146            IF (colvar%population_param%use_kinds_from) THEN
1147               WRITE (iw, '( A,T71,A10)') (' COLVARS| POPULATION based on coordination >>> FROM KINDS', &
1148                                           ADJUSTR(colvar%population_param%c_kinds_from(kk) (1:10)), &
1149                                           kk=1, SIZE(colvar%population_param%c_kinds_from))
1150            ELSE
1151               WRITE (iw, '( A,T71,I10)') (' COLVARS| POPULATION based on coordination >>> FROM '//tag, &
1152                                           colvar%population_param%i_at_from(kk), &
1153                                           kk=1, SIZE(colvar%population_param%i_at_from))
1154            END IF
1155            IF (colvar%population_param%use_kinds_to) THEN
1156               WRITE (iw, '( A,T71,A10)') (' COLVARS| POPULATION based on coordination >>>   TO KINDS', &
1157                                           ADJUSTR(colvar%population_param%c_kinds_to(kk) (1:10)), &
1158                                           kk=1, SIZE(colvar%population_param%c_kinds_to))
1159            ELSE
1160               WRITE (iw, '( A,T71,I10)') (' COLVARS| POPULATION based on coordination   >>>   TO '//tag, &
1161                                           colvar%population_param%i_at_to(kk), &
1162                                           kk=1, SIZE(colvar%population_param%i_at_to))
1163            END IF
1164            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| R0', colvar%population_param%r_0
1165            WRITE (iw, '( A,T71,I10)') ' COLVARS| NN', colvar%population_param%nncrd
1166            WRITE (iw, '( A,T71,I10)') ' COLVARS| ND', colvar%population_param%ndcrd
1167            WRITE (iw, '( A,T71,I10)') ' COLVARS| N0', colvar%population_param%n0
1168            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| SIGMA', colvar%population_param%sigma
1169         CASE (gyration_colvar_id)
1170            IF (colvar%gyration_param%use_kinds) THEN
1171               WRITE (iw, '( A,T71,A10)') (' COLVARS| Gyration Radius >>> KINDS', &
1172                                           ADJUSTR(colvar%gyration_param%c_kinds(kk) (1:10)), &
1173                                           kk=1, SIZE(colvar%gyration_param%c_kinds))
1174            ELSE
1175               WRITE (iw, '( A,T71,I10)') (' COLVARS| Gyration Radius >>> ATOMS '//tag, &
1176                                           colvar%gyration_param%i_at(kk), &
1177                                           kk=1, SIZE(colvar%gyration_param%i_at))
1178            END IF
1179         CASE (rotation_colvar_id)
1180            WRITE (iw, '( A,T71,I10)') ' COLVARS| BOND_ROTATION   - POINT 1 LINE 1  >>> '//tag, &
1181               colvar%rotation_param%i_at1_bond1
1182            WRITE (iw, '( A,T71,I10)') ' COLVARS| BOND_ROTATION   - POINT 2 LINE 1  >>> '//tag, &
1183               colvar%rotation_param%i_at2_bond1
1184            WRITE (iw, '( A,T71,I10)') ' COLVARS| BOND_ROTATION   - POINT 1 LINE 2  >>> '//tag, &
1185               colvar%rotation_param%i_at1_bond2
1186            WRITE (iw, '( A,T71,I10)') ' COLVARS| BOND_ROTATION   - POINT 2 LINE 2  >>> '//tag, &
1187               colvar%rotation_param%i_at2_bond2
1188         CASE (qparm_colvar_id)
1189            WRITE (iw, '( A,T71,I10)') (' COLVARS| Q-PARM  >>> FROM '//tag, &
1190                                        colvar%qparm_param%i_at_from(kk), &
1191                                        kk=1, SIZE(colvar%qparm_param%i_at_from))
1192            WRITE (iw, '( A,T71,I10)') (' COLVARS| Q-PARM  >>>   TO '//tag, &
1193                                        colvar%qparm_param%i_at_to(kk), &
1194                                        kk=1, SIZE(colvar%qparm_param%i_at_to))
1195            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| RCUT', colvar%qparm_param%rcut
1196            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| RSTART', colvar%qparm_param%rstart
1197            WRITE (iw, '( A,T71,L10)') ' COLVARS| INCLUDE IMAGES', colvar%qparm_param%include_images
1198            !WRITE (iw, '( A,T71,F10.5)') ' COLVARS| ALPHA', colvar%qparm_param%alpha
1199            WRITE (iw, '( A,T71,I10)') ' COLVARS| L', colvar%qparm_param%l
1200         CASE (combine_colvar_id)
1201            WRITE (iw, '( A)') ' COLVARS| COMBINING FUNCTION : '// &
1202               TRIM(colvar%combine_cvs_param%function)
1203            WRITE (iw, '( A)', ADVANCE="NO") ' COLVARS| VARIABLES : '
1204            DO i = 1, SIZE(colvar%combine_cvs_param%variables)
1205               WRITE (iw, '( A)', ADVANCE="NO") &
1206                  TRIM(colvar%combine_cvs_param%variables(i))//" "
1207            END DO
1208            WRITE (iw, '(/)')
1209            WRITE (iw, '( A)') ' COLVARS| DEFINED PARAMETERS [label]  [value]:'
1210            DO i = 1, SIZE(colvar%combine_cvs_param%c_parameters)
1211               WRITE (iw, '( A,A7,F9.3)') '                            ', &
1212                  TRIM(colvar%combine_cvs_param%c_parameters(i)), colvar%combine_cvs_param%v_parameters(i)
1213            END DO
1214            WRITE (iw, '( A,T71,G10.5)') ' COLVARS| ERROR ON DERIVATIVE EVALUATION', &
1215               colvar%combine_cvs_param%lerr
1216            WRITE (iw, '( A,T71,G10.5)') ' COLVARS| DX', &
1217               colvar%combine_cvs_param%dx
1218         CASE (reaction_path_colvar_id)
1219            CPWARN("Description header for REACTION_PATH COLVAR missing!!")
1220         CASE (distance_from_path_colvar_id)
1221            CPWARN("Description header for REACTION_PATH COLVAR missing!!")
1222         CASE (hydronium_shell_colvar_id)
1223            WRITE (iw, '( A,T71,I10)') ' COLVARS| POH', colvar%hydronium_shell_param%poh
1224            WRITE (iw, '( A,T71,I10)') ' COLVARS| QOH', colvar%hydronium_shell_param%qoh
1225            WRITE (iw, '( A,T71,I10)') ' COLVARS| POO', colvar%hydronium_shell_param%poo
1226            WRITE (iw, '( A,T71,I10)') ' COLVARS| QOO', colvar%hydronium_shell_param%qoo
1227            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| ROO', colvar%hydronium_shell_param%roo
1228            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| ROH', colvar%hydronium_shell_param%roh
1229            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| NH', colvar%hydronium_shell_param%nh
1230            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| LAMBDA', colvar%hydronium_shell_param%lambda
1231         CASE (hydronium_dist_colvar_id)
1232            WRITE (iw, '( A,T71,I10)') ' COLVARS| POH', colvar%hydronium_dist_param%poh
1233            WRITE (iw, '( A,T71,I10)') ' COLVARS| QOH', colvar%hydronium_dist_param%qoh
1234            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| ROH', colvar%hydronium_dist_param%roh
1235            WRITE (iw, '( A,T71,I10)') ' COLVARS| PM', colvar%hydronium_dist_param%pm
1236            WRITE (iw, '( A,T71,I10)') ' COLVARS| QM', colvar%hydronium_dist_param%qm
1237            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| NH', colvar%hydronium_dist_param%nh
1238            WRITE (iw, '( A,T71,I10)') ' COLVARS| PF', colvar%hydronium_dist_param%pf
1239            WRITE (iw, '( A,T71,I10)') ' COLVARS| QF', colvar%hydronium_dist_param%qf
1240            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| NN', colvar%hydronium_dist_param%nn
1241         CASE (acid_hyd_dist_colvar_id)
1242            WRITE (iw, '( A,T71,I10)') ' COLVARS| PAOH', colvar%acid_hyd_dist_param%paoh
1243            WRITE (iw, '( A,T71,I10)') ' COLVARS| QAOH', colvar%acid_hyd_dist_param%qaoh
1244            WRITE (iw, '( A,T71,I10)') ' COLVARS| PWOH', colvar%acid_hyd_dist_param%pwoh
1245            WRITE (iw, '( A,T71,I10)') ' COLVARS| QWOH', colvar%acid_hyd_dist_param%qwoh
1246            WRITE (iw, '( A,T71,I10)') ' COLVARS| PCUT', colvar%acid_hyd_dist_param%pcut
1247            WRITE (iw, '( A,T71,I10)') ' COLVARS| QCUT', colvar%acid_hyd_dist_param%qcut
1248            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| RAOH', colvar%acid_hyd_dist_param%raoh
1249            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| RWOH', colvar%acid_hyd_dist_param%rwoh
1250            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| NC', colvar%acid_hyd_dist_param%nc
1251            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| LAMBDA', colvar%acid_hyd_dist_param%lambda
1252         CASE (acid_hyd_shell_colvar_id)
1253            WRITE (iw, '( A,T71,I10)') ' COLVARS| PAOH', colvar%acid_hyd_shell_param%paoh
1254            WRITE (iw, '( A,T71,I10)') ' COLVARS| QAOH', colvar%acid_hyd_shell_param%qaoh
1255            WRITE (iw, '( A,T71,I10)') ' COLVARS| PWOH', colvar%acid_hyd_shell_param%pwoh
1256            WRITE (iw, '( A,T71,I10)') ' COLVARS| QWOH', colvar%acid_hyd_shell_param%qwoh
1257            WRITE (iw, '( A,T71,I10)') ' COLVARS| POO', colvar%acid_hyd_shell_param%poo
1258            WRITE (iw, '( A,T71,I10)') ' COLVARS| QOO', colvar%acid_hyd_shell_param%qoo
1259            WRITE (iw, '( A,T71,I10)') ' COLVARS| PM', colvar%acid_hyd_shell_param%pm
1260            WRITE (iw, '( A,T71,I10)') ' COLVARS| QM', colvar%acid_hyd_shell_param%qm
1261            WRITE (iw, '( A,T71,I10)') ' COLVARS| PCUT', colvar%acid_hyd_shell_param%pcut
1262            WRITE (iw, '( A,T71,I10)') ' COLVARS| QCUT', colvar%acid_hyd_shell_param%qcut
1263            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| RAOH', colvar%acid_hyd_shell_param%raoh
1264            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| RWOH', colvar%acid_hyd_shell_param%rwoh
1265            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| ROO', colvar%acid_hyd_shell_param%roo
1266            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| NH', colvar%acid_hyd_shell_param%nh
1267            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| NC', colvar%acid_hyd_shell_param%nc
1268            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| LAMBDA', colvar%acid_hyd_shell_param%lambda
1269         CASE (rmsd_colvar_id)
1270            CPWARN("Description header for RMSD COLVAR missing!!")
1271         CASE (xyz_diag_colvar_id)
1272            NULLIFY (section, keyword, enum)
1273            CALL create_colvar_xyz_d_section(section)
1274            keyword => section_get_keyword(section, "COMPONENT")
1275            CALL keyword_get(keyword, enum=enum)
1276            tag_comp = enum_i2c(enum, colvar%xyz_diag_param%component)
1277            CALL section_release(section)
1278
1279            WRITE (iw, '( A,T57,3I8)') ' COLVARS| POSITION ('//TRIM(tag_comp) &
1280               //')  >>> '//tag, colvar%xyz_diag_param%i_atom
1281         CASE (xyz_outerdiag_colvar_id)
1282            NULLIFY (section, keyword, enum)
1283            CALL create_colvar_xyz_od_section(section)
1284            keyword => section_get_keyword(section, "COMPONENT_A")
1285            CALL keyword_get(keyword, enum=enum)
1286            tag_comp1 = enum_i2c(enum, colvar%xyz_outerdiag_param%components(1))
1287            keyword => section_get_keyword(section, "COMPONENT_B")
1288            CALL keyword_get(keyword, enum=enum)
1289            tag_comp2 = enum_i2c(enum, colvar%xyz_outerdiag_param%components(2))
1290            CALL section_release(section)
1291
1292            WRITE (iw, '( A,T57,3I8)') ' COLVARS| CROSS TERM POSITION ('//TRIM(tag_comp1) &
1293               //" * "//TRIM(tag_comp2)//')  >>> '//tag, colvar%xyz_outerdiag_param%i_atoms
1294         CASE (u_colvar_id)
1295            WRITE (iw, '( A,T77,A4)') ' COLVARS| ENERGY          >>> '//tag, 'all!'
1296         CASE (Wc_colvar_id)
1297            WRITE (iw, '( A,T57,F16.8)') ' COLVARS| Wc          >>> RCUT: ', &
1298               colvar%Wc%rcut
1299            WRITE (iw, '( A,T57,3I8)') ' COLVARS| Wc          >>> '//tag, &
1300               colvar%Wc%ids
1301         CASE (HBP_colvar_id)
1302            WRITE (iw, '( A,T57,I8)') ' COLVARS| HBP          >>> NPOINTS', &
1303               colvar%HBP%nPoints
1304            WRITE (iw, '( A,T57,F16.8)') ' COLVARS| HBP          >>> RCUT', &
1305               colvar%HBP%rcut
1306            WRITE (iw, '( A,T57,F16.8)') ' COLVARS| HBP          >>> RCUT', &
1307               colvar%HBP%shift
1308            DO i = 1, colvar%HBP%nPoints
1309               WRITE (iw, '( A,T57,3I8)') ' COLVARS| HBP          >>> '//tag, &
1310                  colvar%HBP%ids(i, :)
1311            ENDDO
1312         CASE (ring_puckering_colvar_id)
1313            WRITE (iw, '( A,T57,I8)') ' COLVARS| Ring Puckering      >>> ring size', &
1314               colvar%ring_puckering_param%nring
1315            IF (colvar%ring_puckering_param%iq == 0) THEN
1316               WRITE (iw, '( A,T40,A)') ' COLVARS| Ring Puckering      >>> coordinate', &
1317                  ' Total Puckering Amplitude'
1318            ELSEIF (colvar%ring_puckering_param%iq > 0) THEN
1319               WRITE (iw, '( A,T35,A,T57,I8)') ' COLVARS| Ring Puckering      >>> coordinate', &
1320                  ' Puckering Amplitude', &
1321                  colvar%ring_puckering_param%iq
1322            ELSE
1323               WRITE (iw, '( A,T35,A,T57,I8)') ' COLVARS| Ring Puckering      >>> coordinate', &
1324                  ' Puckering Angle', &
1325                  colvar%ring_puckering_param%iq
1326            END IF
1327         CASE (mindist_colvar_id)
1328            WRITE (iw, '( A)') ' COLVARS| CONDITIONED DISTANCE>> '
1329            WRITE (iw, '( A,T71,I10)') (' COLVARS| COND.DISTANCE  >>> DISTANCE FROM '//tag, &
1330                                        colvar%mindist_param%i_dist_from(kk), &
1331                                        kk=1, SIZE(colvar%mindist_param%i_dist_from))
1332            IF (colvar%mindist_param%use_kinds_from) THEN
1333               WRITE (iw, '( A,T71,A10)') (' COLVARS| COND.DIST.  >>> COORDINATION FROM KINDS ', &
1334                                           ADJUSTR(colvar%mindist_param%k_coord_from(kk) (1:10)), &
1335                                           kk=1, SIZE(colvar%mindist_param%k_coord_from))
1336            ELSE
1337               WRITE (iw, '( A,T71,I10)') (' COLVARS| COND.DIST.  >>> COORDINATION FROM '//tag, &
1338                                           colvar%mindist_param%i_coord_from(kk), &
1339                                           kk=1, SIZE(colvar%mindist_param%i_coord_from))
1340            END IF
1341            IF (colvar%mindist_param%use_kinds_to) THEN
1342               WRITE (iw, '( A,T71,A10)') (' COLVARS| COND.DIST.  >>> COORDINATION TO KINDS ', &
1343                                           ADJUSTR(colvar%mindist_param%k_coord_to(kk) (1:10)), &
1344                                           kk=1, SIZE(colvar%mindist_param%k_coord_to))
1345            ELSE
1346               WRITE (iw, '( A,T71,I10)') (' COLVARS| COND.DIST.  >>> COORDINATION TO '//tag, &
1347                                           colvar%mindist_param%i_coord_to(kk), &
1348                                           kk=1, SIZE(colvar%mindist_param%i_coord_to))
1349            END IF
1350            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| R0', colvar%mindist_param%r_cut
1351            WRITE (iw, '( A,T71,I10)') ' COLVARS| NN', colvar%mindist_param%p_exp
1352            WRITE (iw, '( A,T71,I10)') ' COLVARS| ND', colvar%mindist_param%q_exp
1353            WRITE (iw, '( A,T71,F10.5)') ' COLVARS| LAMBDA', colvar%mindist_param%lambda
1354
1355         END SELECT
1356         IF (colvar%use_points) THEN
1357            WRITE (iw, '( A)') ' COLVARS| INFORMATION ON DEFINED GEOMETRICAL POINTS'
1358            DO kk = 1, SIZE(colvar%points)
1359               point_section => section_vals_get_subs_vals(wrk_section, "POINT")
1360               CALL section_vals_val_get(point_section, "TYPE", i_rep_section=kk, c_val=tmpStr)
1361               tmpStr2 = cp_to_string(kk)
1362               WRITE (iw, '( A)') ' COLVARS|  POINT Nr.'//TRIM(tmpStr2)//' OF TYPE: '//TRIM(tmpStr)
1363               IF (ASSOCIATED(colvar%points(kk)%atoms)) THEN
1364                  WRITE (iw, '( A)') ' COLVARS|   ATOMS BUILDING THE GEOMETRICAL POINT'
1365                  WRITE (iw, '( A, I10)') (' COLVARS|   ATOM:', colvar%points(kk)%atoms(k), k=1, SIZE(colvar%points(kk)%atoms))
1366               ELSE
1367                  WRITE (iw, '( A,4X,3F12.6)') ' COLVARS|   XYZ POSITION OF FIXED POINT:', colvar%points(kk)%r
1368               END IF
1369            END DO
1370         END IF
1371         ! Close the description layer
1372         IF (colvar%type_id /= combine_colvar_id) THEN
1373            WRITE (iw, '( A )') '          '// &
1374               '----------------------------------------------------------------------'
1375         ELSE
1376            WRITE (iw, '( A )') '          '// &
1377               '**********************************************************************'
1378         END IF
1379      END IF
1380      CALL cp_print_key_finished_output(iw, logger, colvar_section, &
1381                                        "PRINT%PROGRAM_RUN_INFO")
1382      CALL timestop(handle)
1383   END SUBROUTINE colvar_read
1384
1385! **************************************************************************************************
1386!> \brief read collective variables for the autoionization of water
1387!> \param section ...
1388!> \param colvar collective variable
1389!> \param colvar_id  ...
1390!> \param n_oxygens number of oxygens
1391!> \param n_hydrogens number of hydrogens
1392!> \param i_oxygens list of oxygens
1393!> \param i_hydrogens list of hydrogens
1394!> \author Dorothea Golze
1395! **************************************************************************************************
1396   SUBROUTINE read_hydronium_colvars(section, colvar, colvar_id, n_oxygens, n_hydrogens, &
1397                                     i_oxygens, i_hydrogens)
1398      TYPE(section_vals_type), POINTER                   :: section
1399      TYPE(colvar_type), POINTER                         :: colvar
1400      INTEGER, INTENT(IN)                                :: colvar_id
1401      INTEGER, INTENT(OUT)                               :: n_oxygens, n_hydrogens
1402      INTEGER, DIMENSION(:), POINTER                     :: i_oxygens, i_hydrogens
1403
1404      CHARACTER(len=*), PARAMETER :: routineN = 'read_hydronium_colvars', &
1405         routineP = moduleN//':'//routineN
1406
1407      INTEGER                                            :: k, n_var, ndim
1408      INTEGER, DIMENSION(:), POINTER                     :: iatms
1409
1410      NULLIFY (iatms)
1411
1412      CALL section_vals_val_get(section, "OXYGENS", n_rep_val=n_var)
1413      ndim = 0
1414      DO k = 1, n_var
1415         CALL section_vals_val_get(section, "OXYGENS", i_vals=iatms)
1416         CALL reallocate(i_oxygens, 1, ndim + SIZE(iatms))
1417         i_oxygens(ndim + 1:ndim + SIZE(iatms)) = iatms
1418         ndim = ndim + SIZE(iatms)
1419      END DO
1420      n_oxygens = ndim
1421
1422      CALL section_vals_val_get(section, "HYDROGENS", n_rep_val=n_var)
1423      ndim = 0
1424      DO k = 1, n_var
1425         CALL section_vals_val_get(section, "HYDROGENS", i_vals=iatms)
1426         CALL reallocate(i_hydrogens, 1, ndim + SIZE(iatms))
1427         i_hydrogens(ndim + 1:ndim + SIZE(iatms)) = iatms
1428         ndim = ndim + SIZE(iatms)
1429      END DO
1430      n_hydrogens = ndim
1431
1432      SELECT CASE (colvar_id)
1433      CASE (hydronium_shell_colvar_id)
1434         CALL section_vals_val_get(section, "ROO", r_val=colvar%hydronium_shell_param%roo)
1435         CALL section_vals_val_get(section, "ROH", r_val=colvar%hydronium_shell_param%roh)
1436         CALL section_vals_val_get(section, "pOH", i_val=colvar%hydronium_shell_param%poh)
1437         CALL section_vals_val_get(section, "qOH", i_val=colvar%hydronium_shell_param%qoh)
1438         CALL section_vals_val_get(section, "pOO", i_val=colvar%hydronium_shell_param%poo)
1439         CALL section_vals_val_get(section, "qOO", i_val=colvar%hydronium_shell_param%qoo)
1440         CALL section_vals_val_get(section, "pM", i_val=colvar%hydronium_shell_param%pm)
1441         CALL section_vals_val_get(section, "qM", i_val=colvar%hydronium_shell_param%qm)
1442         CALL section_vals_val_get(section, "NH", r_val=colvar%hydronium_shell_param%nh)
1443         CALL section_vals_val_get(section, "LAMBDA", r_val=colvar%hydronium_shell_param%lambda)
1444      CASE (hydronium_dist_colvar_id)
1445         CALL section_vals_val_get(section, "ROH", r_val=colvar%hydronium_dist_param%roh)
1446         CALL section_vals_val_get(section, "pOH", i_val=colvar%hydronium_dist_param%poh)
1447         CALL section_vals_val_get(section, "qOH", i_val=colvar%hydronium_dist_param%qoh)
1448         CALL section_vals_val_get(section, "pF", i_val=colvar%hydronium_dist_param%pf)
1449         CALL section_vals_val_get(section, "qF", i_val=colvar%hydronium_dist_param%qf)
1450         CALL section_vals_val_get(section, "pM", i_val=colvar%hydronium_dist_param%pm)
1451         CALL section_vals_val_get(section, "qM", i_val=colvar%hydronium_dist_param%qm)
1452         CALL section_vals_val_get(section, "NH", r_val=colvar%hydronium_dist_param%nh)
1453         CALL section_vals_val_get(section, "NN", r_val=colvar%hydronium_dist_param%nn)
1454         CALL section_vals_val_get(section, "LAMBDA", r_val=colvar%hydronium_dist_param%lambda)
1455      END SELECT
1456
1457   END SUBROUTINE read_hydronium_colvars
1458
1459! **************************************************************************************************
1460!> \brief read collective variables for the dissociation of a carboxylic acid
1461!>        in water
1462!> \param section ...
1463!> \param colvar collective variable
1464!> \param colvar_id  ...
1465!> \param n_oxygens_water number of oxygens of water molecules
1466!> \param n_oxygens_acid number of oxgyens of carboxyl groups
1467!> \param n_hydrogens number of hydrogens (water and carboxyl group)
1468!> \param i_oxygens_water list of oxygens of water molecules
1469!> \param i_oxygens_acid list of oxygens of carboxyl group
1470!> \param i_hydrogens list of hydrogens (water and carboxyl group)
1471!> \author Dorothea Golze
1472! **************************************************************************************************
1473   SUBROUTINE read_acid_hydronium_colvars(section, colvar, colvar_id, n_oxygens_water, &
1474                                          n_oxygens_acid, n_hydrogens, i_oxygens_water, &
1475                                          i_oxygens_acid, i_hydrogens)
1476      TYPE(section_vals_type), POINTER                   :: section
1477      TYPE(colvar_type), POINTER                         :: colvar
1478      INTEGER, INTENT(IN)                                :: colvar_id
1479      INTEGER, INTENT(OUT)                               :: n_oxygens_water, n_oxygens_acid, &
1480                                                            n_hydrogens
1481      INTEGER, DIMENSION(:), POINTER                     :: i_oxygens_water, i_oxygens_acid, &
1482                                                            i_hydrogens
1483
1484      CHARACTER(len=*), PARAMETER :: routineN = 'read_acid_hydronium_colvars', &
1485         routineP = moduleN//':'//routineN
1486
1487      INTEGER                                            :: k, n_var, ndim
1488      INTEGER, DIMENSION(:), POINTER                     :: iatms
1489
1490      NULLIFY (iatms)
1491
1492      CALL section_vals_val_get(section, "OXYGENS_WATER", n_rep_val=n_var)
1493      ndim = 0
1494      DO k = 1, n_var
1495         CALL section_vals_val_get(section, "OXYGENS_WATER", i_vals=iatms)
1496         CALL reallocate(i_oxygens_water, 1, ndim + SIZE(iatms))
1497         i_oxygens_water(ndim + 1:ndim + SIZE(iatms)) = iatms
1498         ndim = ndim + SIZE(iatms)
1499      END DO
1500      n_oxygens_water = ndim
1501
1502      CALL section_vals_val_get(section, "OXYGENS_ACID", n_rep_val=n_var)
1503      ndim = 0
1504      DO k = 1, n_var
1505         CALL section_vals_val_get(section, "OXYGENS_ACID", i_vals=iatms)
1506         CALL reallocate(i_oxygens_acid, 1, ndim + SIZE(iatms))
1507         i_oxygens_acid(ndim + 1:ndim + SIZE(iatms)) = iatms
1508         ndim = ndim + SIZE(iatms)
1509      END DO
1510      n_oxygens_acid = ndim
1511
1512      CALL section_vals_val_get(section, "HYDROGENS", n_rep_val=n_var)
1513      ndim = 0
1514      DO k = 1, n_var
1515         CALL section_vals_val_get(section, "HYDROGENS", i_vals=iatms)
1516         CALL reallocate(i_hydrogens, 1, ndim + SIZE(iatms))
1517         i_hydrogens(ndim + 1:ndim + SIZE(iatms)) = iatms
1518         ndim = ndim + SIZE(iatms)
1519      END DO
1520      n_hydrogens = ndim
1521
1522      SELECT CASE (colvar_id)
1523      CASE (acid_hyd_dist_colvar_id)
1524         CALL section_vals_val_get(section, "pWOH", i_val=colvar%acid_hyd_dist_param%pwoh)
1525         CALL section_vals_val_get(section, "qWOH", i_val=colvar%acid_hyd_dist_param%qwoh)
1526         CALL section_vals_val_get(section, "pAOH", i_val=colvar%acid_hyd_dist_param%paoh)
1527         CALL section_vals_val_get(section, "qAOH", i_val=colvar%acid_hyd_dist_param%qaoh)
1528         CALL section_vals_val_get(section, "pCUT", i_val=colvar%acid_hyd_dist_param%pcut)
1529         CALL section_vals_val_get(section, "qCUT", i_val=colvar%acid_hyd_dist_param%qcut)
1530         CALL section_vals_val_get(section, "RWOH", r_val=colvar%acid_hyd_dist_param%rwoh)
1531         CALL section_vals_val_get(section, "RAOH", r_val=colvar%acid_hyd_dist_param%raoh)
1532         CALL section_vals_val_get(section, "NC", r_val=colvar%acid_hyd_dist_param%nc)
1533         CALL section_vals_val_get(section, "LAMBDA", r_val=colvar%acid_hyd_dist_param%lambda)
1534      CASE (acid_hyd_shell_colvar_id)
1535         CALL section_vals_val_get(section, "pWOH", i_val=colvar%acid_hyd_shell_param%pwoh)
1536         CALL section_vals_val_get(section, "qWOH", i_val=colvar%acid_hyd_shell_param%qwoh)
1537         CALL section_vals_val_get(section, "pAOH", i_val=colvar%acid_hyd_shell_param%paoh)
1538         CALL section_vals_val_get(section, "qAOH", i_val=colvar%acid_hyd_shell_param%qaoh)
1539         CALL section_vals_val_get(section, "pOO", i_val=colvar%acid_hyd_shell_param%poo)
1540         CALL section_vals_val_get(section, "qOO", i_val=colvar%acid_hyd_shell_param%qoo)
1541         CALL section_vals_val_get(section, "pM", i_val=colvar%acid_hyd_shell_param%pm)
1542         CALL section_vals_val_get(section, "qM", i_val=colvar%acid_hyd_shell_param%qm)
1543         CALL section_vals_val_get(section, "pCUT", i_val=colvar%acid_hyd_shell_param%pcut)
1544         CALL section_vals_val_get(section, "qCUT", i_val=colvar%acid_hyd_shell_param%qcut)
1545         CALL section_vals_val_get(section, "RWOH", r_val=colvar%acid_hyd_shell_param%rwoh)
1546         CALL section_vals_val_get(section, "RAOH", r_val=colvar%acid_hyd_shell_param%raoh)
1547         CALL section_vals_val_get(section, "ROO", r_val=colvar%acid_hyd_shell_param%roo)
1548         CALL section_vals_val_get(section, "NC", r_val=colvar%acid_hyd_shell_param%nc)
1549         CALL section_vals_val_get(section, "NH", r_val=colvar%acid_hyd_shell_param%nh)
1550         CALL section_vals_val_get(section, "LAMBDA", r_val=colvar%acid_hyd_shell_param%lambda)
1551      END SELECT
1552
1553   END SUBROUTINE read_acid_hydronium_colvars
1554
1555! **************************************************************************************************
1556!> \brief Check and setup about the use of geometrical points instead of atoms
1557!> \param colvar the colvat to initialize
1558!> \param section ...
1559!> \author Teodoro Laino, [teo] 03.2007
1560! **************************************************************************************************
1561   SUBROUTINE colvar_check_points(colvar, section)
1562      TYPE(colvar_type), POINTER                         :: colvar
1563      TYPE(section_vals_type), POINTER                   :: section
1564
1565      CHARACTER(len=*), PARAMETER :: routineN = 'colvar_check_points', &
1566         routineP = moduleN//':'//routineN
1567
1568      INTEGER                                            :: i, irep, natoms, npoints, nrep, nweights
1569      INTEGER, DIMENSION(:), POINTER                     :: atoms
1570      LOGICAL                                            :: explicit
1571      REAL(KIND=dp), DIMENSION(:), POINTER               :: r, weights
1572      TYPE(section_vals_type), POINTER                   :: point_sections
1573
1574      NULLIFY (point_sections)
1575      NULLIFY (atoms)
1576      NULLIFY (weights)
1577      CPASSERT(ASSOCIATED(colvar))
1578      point_sections => section_vals_get_subs_vals(section, "POINT")
1579      CALL section_vals_get(point_sections, explicit=explicit)
1580      IF (explicit) THEN
1581         colvar%use_points = .TRUE.
1582         CALL section_vals_get(point_sections, n_repetition=npoints)
1583         ALLOCATE (colvar%points(npoints))
1584         ! Read points definition
1585         DO i = 1, npoints
1586            natoms = 0
1587            nweights = 0
1588            NULLIFY (colvar%points(i)%atoms)
1589            NULLIFY (colvar%points(i)%weights)
1590            CALL section_vals_val_get(point_sections, "TYPE", i_rep_section=i, i_val=colvar%points(i)%type_id)
1591            SELECT CASE (colvar%points(i)%type_id)
1592            CASE (do_clv_geo_center)
1593               ! Define a point through a list of atoms..
1594               CALL section_vals_val_get(point_sections, "ATOMS", i_rep_section=i, n_rep_val=nrep, i_vals=atoms)
1595               DO irep = 1, nrep
1596                  CALL section_vals_val_get(point_sections, "ATOMS", i_rep_section=i, i_rep_val=irep, i_vals=atoms)
1597                  natoms = natoms + SIZE(atoms)
1598               END DO
1599               ALLOCATE (colvar%points(i)%atoms(natoms))
1600               natoms = 0
1601               DO irep = 1, nrep
1602                  CALL section_vals_val_get(point_sections, "ATOMS", i_rep_section=i, i_rep_val=irep, i_vals=atoms)
1603                  colvar%points(i)%atoms(natoms + 1:) = atoms(:)
1604                  natoms = natoms + SIZE(atoms)
1605               END DO
1606               ! Define weights of the list
1607               ALLOCATE (colvar%points(i)%weights(natoms))
1608               colvar%points(i)%weights = 1.0_dp/REAL(natoms, KIND=dp)
1609               CALL section_vals_val_get(point_sections, "WEIGHTS", i_rep_section=i, n_rep_val=nrep)
1610               IF (nrep /= 0) THEN
1611                  DO irep = 1, nrep
1612                     CALL section_vals_val_get(point_sections, "WEIGHTS", i_rep_section=i, i_rep_val=irep, &
1613                                               r_vals=weights)
1614                     colvar%points(i)%weights(nweights + 1:) = weights(:)
1615                     nweights = nweights + SIZE(weights)
1616                  END DO
1617                  CPASSERT(natoms == nweights)
1618               END IF
1619            CASE (do_clv_fix_point)
1620               ! Define the point as a fixed point in space..
1621               CALL section_vals_val_get(point_sections, "XYZ", i_rep_section=i, r_vals=r)
1622               colvar%points(i)%r = r
1623            END SELECT
1624         END DO
1625      END IF
1626   END SUBROUTINE colvar_check_points
1627
1628! **************************************************************************************************
1629!> \brief evaluates the derivatives (dsdr) given and due to the given colvar
1630!>      variables in a molecular environment
1631!> \param colvar the collective variable to evaluate
1632!> \param cell ...
1633!> \param particles ...
1634!> \param pos ...
1635!> \param fixd_list ...
1636!> \author Teodoro Laino
1637! **************************************************************************************************
1638   SUBROUTINE colvar_eval_mol_f(colvar, cell, particles, pos, fixd_list)
1639      TYPE(colvar_type), POINTER                         :: colvar
1640      TYPE(cell_type), POINTER                           :: cell
1641      TYPE(particle_type), DIMENSION(:), POINTER         :: particles
1642      REAL(kind=dp), DIMENSION(:, :), INTENT(IN), &
1643         OPTIONAL                                        :: pos
1644      TYPE(fixd_constraint_type), DIMENSION(:), &
1645         OPTIONAL, POINTER                               :: fixd_list
1646
1647      CHARACTER(len=*), PARAMETER :: routineN = 'colvar_eval_mol_f', &
1648         routineP = moduleN//':'//routineN
1649
1650      INTEGER                                            :: i, j
1651      LOGICAL                                            :: colvar_ok
1652
1653      colvar_ok = ASSOCIATED(colvar)
1654      CPASSERT(colvar_ok)
1655
1656      IF (PRESENT(pos)) THEN
1657         DO i = 1, SIZE(colvar%i_atom)
1658            j = colvar%i_atom(i)
1659            particles(j)%r = pos(:, j)
1660         END DO
1661      END IF
1662      ! Initialize the content of the derivative
1663      colvar%dsdr = 0.0_dp
1664      SELECT CASE (colvar%type_id)
1665      CASE (dist_colvar_id)
1666         CALL dist_colvar(colvar, cell, particles=particles)
1667      CASE (coord_colvar_id)
1668         CALL coord_colvar(colvar, cell, particles=particles)
1669      CASE (population_colvar_id)
1670         CALL population_colvar(colvar, cell, particles=particles)
1671      CASE (gyration_colvar_id)
1672         CALL gyration_radius_colvar(colvar, cell, particles=particles)
1673      CASE (torsion_colvar_id)
1674         CALL torsion_colvar(colvar, cell, particles=particles)
1675      CASE (angle_colvar_id)
1676         CALL angle_colvar(colvar, cell, particles=particles)
1677      CASE (dfunct_colvar_id)
1678         CALL dfunct_colvar(colvar, cell, particles=particles)
1679      CASE (plane_distance_colvar_id)
1680         CALL plane_distance_colvar(colvar, cell, particles=particles)
1681      CASE (plane_plane_angle_colvar_id)
1682         CALL plane_plane_angle_colvar(colvar, cell, particles=particles)
1683      CASE (rotation_colvar_id)
1684         CALL rotation_colvar(colvar, cell, particles=particles)
1685      CASE (qparm_colvar_id)
1686         CALL qparm_colvar(colvar, cell, particles=particles)
1687      CASE (hydronium_shell_colvar_id)
1688         CALL hydronium_shell_colvar(colvar, cell, particles=particles)
1689      CASE (hydronium_dist_colvar_id)
1690         CALL hydronium_dist_colvar(colvar, cell, particles=particles)
1691      CASE (acid_hyd_dist_colvar_id)
1692         CALL acid_hyd_dist_colvar(colvar, cell, particles=particles)
1693      CASE (acid_hyd_shell_colvar_id)
1694         CALL acid_hyd_shell_colvar(colvar, cell, particles=particles)
1695      CASE (rmsd_colvar_id)
1696         CALL rmsd_colvar(colvar, particles=particles)
1697      CASE (reaction_path_colvar_id)
1698         CALL reaction_path_colvar(colvar, cell, particles=particles)
1699      CASE (distance_from_path_colvar_id)
1700         CALL distance_from_path_colvar(colvar, cell, particles=particles)
1701      CASE (combine_colvar_id)
1702         CALL combine_colvar(colvar, cell, particles=particles)
1703      CASE (xyz_diag_colvar_id)
1704         CALL xyz_diag_colvar(colvar, cell, particles=particles)
1705      CASE (xyz_outerdiag_colvar_id)
1706         CALL xyz_outerdiag_colvar(colvar, cell, particles=particles)
1707      CASE (ring_puckering_colvar_id)
1708         CALL ring_puckering_colvar(colvar, cell, particles=particles)
1709      CASE (mindist_colvar_id)
1710         CALL mindist_colvar(colvar, cell, particles=particles)
1711      CASE (u_colvar_id)
1712         CPABORT("need force_env!")
1713      CASE (Wc_colvar_id)
1714         !!! FIXME this is rubbish at the moment as we have no force to be computed on this
1715         CALL Wc_colvar(colvar, cell, particles=particles)
1716      CASE (HBP_colvar_id)
1717         !!! FIXME this is rubbish at the moment as we have no force to be computed on this
1718         CALL HBP_colvar(colvar, cell, particles=particles)
1719      CASE DEFAULT
1720         CPABORT("")
1721      END SELECT
1722      ! Check for fixed atom constraints
1723      IF (PRESENT(fixd_list)) CALL check_fixed_atom_cns_colv(fixd_list, colvar)
1724
1725   END SUBROUTINE colvar_eval_mol_f
1726
1727! **************************************************************************************************
1728!> \brief evaluates the derivatives (dsdr) given and due to the given colvar
1729!> \param icolvar the collective variable to evaluate
1730!> \param force_env ...
1731!> \author Alessandro Laio and fawzi
1732!> \note
1733!>      The torsion that generally is defined without the continuity problem
1734!>      here (for free energy calculations) is defined only for (-pi,pi]
1735! **************************************************************************************************
1736   SUBROUTINE colvar_eval_glob_f(icolvar, force_env)
1737      INTEGER                                            :: icolvar
1738      TYPE(force_env_type), POINTER                      :: force_env
1739
1740      CHARACTER(len=*), PARAMETER :: routineN = 'colvar_eval_glob_f', &
1741         routineP = moduleN//':'//routineN
1742
1743      LOGICAL                                            :: colvar_ok
1744      TYPE(cell_type), POINTER                           :: cell
1745      TYPE(colvar_type), POINTER                         :: colvar
1746      TYPE(cp_subsys_type), POINTER                      :: subsys
1747      TYPE(qs_environment_type), POINTER                 :: qs_env
1748
1749      NULLIFY (subsys, cell, colvar, qs_env)
1750      CALL force_env_get(force_env, subsys=subsys, cell=cell, qs_env=qs_env)
1751      colvar_ok = ASSOCIATED(subsys%colvar_p)
1752      CPASSERT(colvar_ok)
1753
1754      colvar => subsys%colvar_p(icolvar)%colvar
1755      ! Initialize the content of the derivative
1756      colvar%dsdr = 0.0_dp
1757      SELECT CASE (colvar%type_id)
1758      CASE (dist_colvar_id)
1759         CALL dist_colvar(colvar, cell, subsys=subsys)
1760      CASE (coord_colvar_id)
1761         CALL coord_colvar(colvar, cell, subsys=subsys)
1762      CASE (population_colvar_id)
1763         CALL population_colvar(colvar, cell, subsys=subsys)
1764      CASE (gyration_colvar_id)
1765         CALL gyration_radius_colvar(colvar, cell, subsys=subsys)
1766      CASE (torsion_colvar_id)
1767         CALL torsion_colvar(colvar, cell, subsys=subsys, no_riemann_sheet_op=.TRUE.)
1768      CASE (angle_colvar_id)
1769         CALL angle_colvar(colvar, cell, subsys=subsys)
1770      CASE (dfunct_colvar_id)
1771         CALL dfunct_colvar(colvar, cell, subsys=subsys)
1772      CASE (plane_distance_colvar_id)
1773         CALL plane_distance_colvar(colvar, cell, subsys=subsys)
1774      CASE (plane_plane_angle_colvar_id)
1775         CALL plane_plane_angle_colvar(colvar, cell, subsys=subsys)
1776      CASE (rotation_colvar_id)
1777         CALL rotation_colvar(colvar, cell, subsys=subsys)
1778      CASE (qparm_colvar_id)
1779         CALL qparm_colvar(colvar, cell, subsys=subsys)
1780      CASE (hydronium_shell_colvar_id)
1781         CALL hydronium_shell_colvar(colvar, cell, subsys=subsys)
1782      CASE (hydronium_dist_colvar_id)
1783         CALL hydronium_dist_colvar(colvar, cell, subsys=subsys)
1784      CASE (acid_hyd_dist_colvar_id)
1785         CALL acid_hyd_dist_colvar(colvar, cell, subsys=subsys)
1786      CASE (acid_hyd_shell_colvar_id)
1787         CALL acid_hyd_shell_colvar(colvar, cell, subsys=subsys)
1788      CASE (rmsd_colvar_id)
1789         CALL rmsd_colvar(colvar, subsys=subsys)
1790      CASE (reaction_path_colvar_id)
1791         CALL reaction_path_colvar(colvar, cell, subsys=subsys)
1792      CASE (distance_from_path_colvar_id)
1793         CALL distance_from_path_colvar(colvar, cell, subsys=subsys)
1794      CASE (combine_colvar_id)
1795         CALL combine_colvar(colvar, cell, subsys=subsys)
1796      CASE (xyz_diag_colvar_id)
1797         CALL xyz_diag_colvar(colvar, cell, subsys=subsys)
1798      CASE (xyz_outerdiag_colvar_id)
1799         CALL xyz_outerdiag_colvar(colvar, cell, subsys=subsys)
1800      CASE (u_colvar_id)
1801         CALL u_colvar(colvar, force_env=force_env)
1802      CASE (Wc_colvar_id)
1803         CALL Wc_colvar(colvar, cell, subsys=subsys, qs_env=qs_env)
1804      CASE (HBP_colvar_id)
1805         CALL HBP_colvar(colvar, cell, subsys=subsys, qs_env=qs_env)
1806      CASE (ring_puckering_colvar_id)
1807         CALL ring_puckering_colvar(colvar, cell, subsys=subsys)
1808      CASE (mindist_colvar_id)
1809         CALL mindist_colvar(colvar, cell, subsys=subsys)
1810      CASE DEFAULT
1811         CPABORT("")
1812      END SELECT
1813      ! Check for fixed atom constraints
1814      CALL check_fixed_atom_cns_colv(subsys%gci%fixd_list, colvar)
1815   END SUBROUTINE colvar_eval_glob_f
1816
1817! **************************************************************************************************
1818!> \brief evaluates the derivatives (dsdr) given and due to the given colvar
1819!>        for the specification of a recursive colvar type
1820!> \param colvar the collective variable to evaluate
1821!> \param cell ...
1822!> \param particles ...
1823!> \author sfchiff
1824! **************************************************************************************************
1825   SUBROUTINE colvar_recursive_eval(colvar, cell, particles)
1826      TYPE(colvar_type), POINTER                         :: colvar
1827      TYPE(cell_type), POINTER                           :: cell
1828      TYPE(particle_type), DIMENSION(:), POINTER         :: particles
1829
1830      CHARACTER(len=*), PARAMETER :: routineN = 'colvar_recursive_eval', &
1831         routineP = moduleN//':'//routineN
1832
1833! Initialize the content of the derivative
1834
1835      colvar%dsdr = 0.0_dp
1836      SELECT CASE (colvar%type_id)
1837      CASE (dist_colvar_id)
1838         CALL dist_colvar(colvar, cell, particles=particles)
1839      CASE (coord_colvar_id)
1840         CALL coord_colvar(colvar, cell, particles=particles)
1841      CASE (torsion_colvar_id)
1842         CALL torsion_colvar(colvar, cell, particles=particles)
1843      CASE (angle_colvar_id)
1844         CALL angle_colvar(colvar, cell, particles=particles)
1845      CASE (dfunct_colvar_id)
1846         CALL dfunct_colvar(colvar, cell, particles=particles)
1847      CASE (plane_distance_colvar_id)
1848         CALL plane_distance_colvar(colvar, cell, particles=particles)
1849      CASE (plane_plane_angle_colvar_id)
1850         CALL plane_plane_angle_colvar(colvar, cell, particles=particles)
1851      CASE (rotation_colvar_id)
1852         CALL rotation_colvar(colvar, cell, particles=particles)
1853      CASE (qparm_colvar_id)
1854         CALL qparm_colvar(colvar, cell, particles=particles)
1855      CASE (hydronium_shell_colvar_id)
1856         CALL hydronium_shell_colvar(colvar, cell, particles=particles)
1857      CASE (hydronium_dist_colvar_id)
1858         CALL hydronium_dist_colvar(colvar, cell, particles=particles)
1859      CASE (acid_hyd_dist_colvar_id)
1860         CALL acid_hyd_dist_colvar(colvar, cell, particles=particles)
1861      CASE (acid_hyd_shell_colvar_id)
1862         CALL acid_hyd_shell_colvar(colvar, cell, particles=particles)
1863      CASE (rmsd_colvar_id)
1864         CALL rmsd_colvar(colvar, particles=particles)
1865      CASE (reaction_path_colvar_id)
1866         CALL reaction_path_colvar(colvar, cell, particles=particles)
1867      CASE (distance_from_path_colvar_id)
1868         CALL distance_from_path_colvar(colvar, cell, particles=particles)
1869      CASE (combine_colvar_id)
1870         CALL combine_colvar(colvar, cell, particles=particles)
1871      CASE (xyz_diag_colvar_id)
1872         CALL xyz_diag_colvar(colvar, cell, particles=particles)
1873      CASE (xyz_outerdiag_colvar_id)
1874         CALL xyz_outerdiag_colvar(colvar, cell, particles=particles)
1875      CASE (ring_puckering_colvar_id)
1876         CALL ring_puckering_colvar(colvar, cell, particles=particles)
1877      CASE (mindist_colvar_id)
1878         CALL mindist_colvar(colvar, cell, particles=particles)
1879      CASE (u_colvar_id)
1880         CPABORT("need force_env!")
1881      CASE (Wc_colvar_id)
1882         CALL Wc_colvar(colvar, cell, particles=particles)
1883      CASE (HBP_colvar_id)
1884         CALL HBP_colvar(colvar, cell, particles=particles)
1885      CASE DEFAULT
1886         CPABORT("")
1887      END SELECT
1888   END SUBROUTINE colvar_recursive_eval
1889
1890! **************************************************************************************************
1891!> \brief Get coordinates of atoms or of geometrical points
1892!> \param colvar ...
1893!> \param i ...
1894!> \param ri ...
1895!> \param my_particles ...
1896!> \author Teodoro Laino 03.2007 [created]
1897! **************************************************************************************************
1898   SUBROUTINE get_coordinates(colvar, i, ri, my_particles)
1899      TYPE(colvar_type), POINTER                         :: colvar
1900      INTEGER, INTENT(IN)                                :: i
1901      REAL(KIND=dp), DIMENSION(3), INTENT(OUT)           :: ri
1902      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
1903
1904      IF (colvar%use_points) THEN
1905         CALL eval_point_pos(colvar%points(i), my_particles, ri)
1906      ELSE
1907         ri(:) = my_particles(i)%r(:)
1908      END IF
1909
1910   END SUBROUTINE get_coordinates
1911
1912! **************************************************************************************************
1913!> \brief Get masses of atoms or of geometrical points
1914!> \param colvar ...
1915!> \param i ...
1916!> \param mi ...
1917!> \param my_particles ...
1918!> \author Teodoro Laino 03.2007 [created]
1919! **************************************************************************************************
1920   SUBROUTINE get_mass(colvar, i, mi, my_particles)
1921      TYPE(colvar_type), POINTER                         :: colvar
1922      INTEGER, INTENT(IN)                                :: i
1923      REAL(KIND=dp), INTENT(OUT)                         :: mi
1924      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
1925
1926      IF (colvar%use_points) THEN
1927         CALL eval_point_mass(colvar%points(i), my_particles, mi)
1928      ELSE
1929         mi = my_particles(i)%atomic_kind%mass
1930      END IF
1931
1932   END SUBROUTINE get_mass
1933
1934! **************************************************************************************************
1935!> \brief Transfer derivatives to ds/dr
1936!> \param colvar ...
1937!> \param i ...
1938!> \param fi ...
1939!> \author Teodoro Laino 03.2007 [created]
1940! **************************************************************************************************
1941   SUBROUTINE put_derivative(colvar, i, fi)
1942      TYPE(colvar_type), POINTER                         :: colvar
1943      INTEGER, INTENT(IN)                                :: i
1944      REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: fi
1945
1946      IF (colvar%use_points) THEN
1947         CALL eval_point_der(colvar%points, i, colvar%dsdr, fi)
1948      ELSE
1949         colvar%dsdr(:, i) = colvar%dsdr(:, i) + fi
1950      END IF
1951
1952   END SUBROUTINE put_derivative
1953
1954! **************************************************************************************************
1955!> \brief  evaluates the force due to the position colvar
1956!> \param colvar ...
1957!> \param cell ...
1958!> \param subsys ...
1959!> \param particles ...
1960!> \author Teodoro Laino 02.2010 [created]
1961! **************************************************************************************************
1962   SUBROUTINE xyz_diag_colvar(colvar, cell, subsys, particles)
1963      TYPE(colvar_type), POINTER                         :: colvar
1964      TYPE(cell_type), POINTER                           :: cell
1965      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
1966      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
1967         POINTER                                         :: particles
1968
1969      CHARACTER(len=*), PARAMETER :: routineN = 'xyz_diag_colvar', &
1970         routineP = moduleN//':'//routineN
1971
1972      INTEGER                                            :: i
1973      REAL(dp)                                           :: fi(3), r, r0(3), ss(3), xi(3), xpi(3)
1974      TYPE(particle_list_type), POINTER                  :: particles_i
1975      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
1976
1977      NULLIFY (particles_i)
1978
1979      CPASSERT(colvar%type_id == xyz_diag_colvar_id)
1980      IF (PRESENT(particles)) THEN
1981         my_particles => particles
1982      ELSE
1983         CPASSERT(PRESENT(subsys))
1984         CALL cp_subsys_get(subsys, particles=particles_i)
1985         my_particles => particles_i%els
1986      END IF
1987      i = colvar%xyz_diag_param%i_atom
1988      ! Atom coordinates
1989      CALL get_coordinates(colvar, i, xpi, my_particles)
1990      ! Use the current coordinates as initial coordinates, if no initialization
1991      ! was performed yet
1992      IF (.NOT. colvar%xyz_diag_param%use_absolute_position) THEN
1993         IF (ALL(colvar%xyz_diag_param%r0 == HUGE(0.0_dp))) THEN
1994            colvar%xyz_diag_param%r0 = xpi
1995         END IF
1996         r0 = colvar%xyz_diag_param%r0
1997      ELSE
1998         r0 = 0.0_dp
1999      ENDIF
2000
2001      IF (colvar%xyz_diag_param%use_pbc) THEN
2002         ss = MATMUL(cell%h_inv, xpi - r0)
2003         ss = ss - NINT(ss)
2004         xi = MATMUL(cell%hmat, ss)
2005      ELSE
2006         xi = xpi - r0
2007      END IF
2008
2009      IF (.NOT. colvar%xyz_diag_param%use_absolute_position) THEN
2010         SELECT CASE (colvar%xyz_diag_param%component)
2011         CASE (do_clv_x)
2012            xi(2) = 0.0_dp
2013            xi(3) = 0.0_dp
2014         CASE (do_clv_y)
2015            xi(1) = 0.0_dp
2016            xi(3) = 0.0_dp
2017         CASE (do_clv_z)
2018            xi(1) = 0.0_dp
2019            xi(2) = 0.0_dp
2020         CASE (do_clv_xy)
2021            xi(3) = 0.0_dp
2022         CASE (do_clv_xz)
2023            xi(2) = 0.0_dp
2024         CASE (do_clv_yz)
2025            xi(1) = 0.0_dp
2026         CASE DEFAULT
2027            ! do_clv_xyz
2028         END SELECT
2029
2030         r = xi(1)**2 + xi(2)**2 + xi(3)**2
2031         fi(:) = 2.0_dp*xi
2032      ELSE
2033         SELECT CASE (colvar%xyz_diag_param%component)
2034         CASE (do_clv_x)
2035            r = xi(1)
2036            xi(1) = 1.0_dp
2037            xi(2) = 0.0_dp
2038            xi(3) = 0.0_dp
2039         CASE (do_clv_y)
2040            r = xi(2)
2041            xi(1) = 0.0_dp
2042            xi(2) = 1.0_dp
2043            xi(3) = 0.0_dp
2044         CASE (do_clv_z)
2045            r = xi(3)
2046            xi(1) = 0.0_dp
2047            xi(2) = 0.0_dp
2048            xi(3) = 1.0_dp
2049         CASE DEFAULT
2050            !Not implemented for anything which is not a single component.
2051            CPABORT("")
2052         END SELECT
2053         fi(:) = xi
2054      ENDIF
2055
2056      colvar%ss = r
2057      CALL put_derivative(colvar, 1, fi)
2058
2059   END SUBROUTINE xyz_diag_colvar
2060
2061! **************************************************************************************************
2062!> \brief  evaluates the force due to the position colvar
2063!> \param colvar ...
2064!> \param cell ...
2065!> \param subsys ...
2066!> \param particles ...
2067!> \author Teodoro Laino 02.2010 [created]
2068! **************************************************************************************************
2069   SUBROUTINE xyz_outerdiag_colvar(colvar, cell, subsys, particles)
2070      TYPE(colvar_type), POINTER                         :: colvar
2071      TYPE(cell_type), POINTER                           :: cell
2072      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
2073      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
2074         POINTER                                         :: particles
2075
2076      CHARACTER(len=*), PARAMETER :: routineN = 'xyz_outerdiag_colvar', &
2077         routineP = moduleN//':'//routineN
2078
2079      INTEGER                                            :: i, k, l
2080      REAL(dp)                                           :: fi(3, 2), r, r0(3), ss(3), xi(3, 2), &
2081                                                            xpi(3)
2082      TYPE(particle_list_type), POINTER                  :: particles_i
2083      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
2084
2085      NULLIFY (particles_i)
2086
2087      CPASSERT(colvar%type_id == xyz_outerdiag_colvar_id)
2088      IF (PRESENT(particles)) THEN
2089         my_particles => particles
2090      ELSE
2091         CPASSERT(PRESENT(subsys))
2092         CALL cp_subsys_get(subsys, particles=particles_i)
2093         my_particles => particles_i%els
2094      END IF
2095      DO k = 1, 2
2096         i = colvar%xyz_outerdiag_param%i_atoms(k)
2097         ! Atom coordinates
2098         CALL get_coordinates(colvar, i, xpi, my_particles)
2099         r0 = colvar%xyz_outerdiag_param%r0(:, k)
2100         IF (ALL(colvar%xyz_outerdiag_param%r0(:, k) == HUGE(0.0_dp))) r0 = xpi
2101
2102         IF (colvar%xyz_outerdiag_param%use_pbc) THEN
2103            ss = MATMUL(cell%h_inv, xpi - r0)
2104            ss = ss - NINT(ss)
2105            xi(:, k) = MATMUL(cell%hmat, ss)
2106         ELSE
2107            xi(:, k) = xpi - r0
2108         END IF
2109
2110         SELECT CASE (colvar%xyz_outerdiag_param%components(k))
2111         CASE (do_clv_x)
2112            xi(2, k) = 0.0_dp
2113            xi(3, k) = 0.0_dp
2114         CASE (do_clv_y)
2115            xi(1, k) = 0.0_dp
2116            xi(3, k) = 0.0_dp
2117         CASE (do_clv_z)
2118            xi(1, k) = 0.0_dp
2119            xi(2, k) = 0.0_dp
2120         CASE (do_clv_xy)
2121            xi(3, k) = 0.0_dp
2122         CASE (do_clv_xz)
2123            xi(2, k) = 0.0_dp
2124         CASE (do_clv_yz)
2125            xi(1, k) = 0.0_dp
2126         CASE DEFAULT
2127            ! do_clv_xyz
2128         END SELECT
2129      END DO
2130
2131      r = 0.0_dp
2132      fi = 0.0_dp
2133      DO i = 1, 3
2134         DO l = 1, 3
2135            IF (xi(l, 1) /= 0.0_dp) fi(l, 1) = fi(l, 1) + xi(i, 2)
2136            r = r + xi(l, 1)*xi(i, 2)
2137         END DO
2138         IF (xi(i, 2) /= 0.0_dp) fi(i, 2) = SUM(xi(:, 1))
2139      END DO
2140
2141      colvar%ss = r
2142      CALL put_derivative(colvar, 1, fi(:, 1))
2143      CALL put_derivative(colvar, 2, fi(:, 2))
2144
2145   END SUBROUTINE xyz_outerdiag_colvar
2146
2147! **************************************************************************************************
2148!> \brief evaluates the force due (and on) the energy as collective variable
2149!> \param colvar ...
2150!> \param force_env ...
2151!> \par History Modified to allow functions of energy in a mixed_env environment
2152!>              Teodoro Laino [tlaino] - 02.2011
2153!> \author Sebastiano Caravati
2154! **************************************************************************************************
2155   SUBROUTINE u_colvar(colvar, force_env)
2156      TYPE(colvar_type), POINTER                         :: colvar
2157      TYPE(force_env_type), OPTIONAL, POINTER            :: force_env
2158
2159      CHARACTER(len=*), PARAMETER :: routineN = 'u_colvar', routineP = moduleN//':'//routineN
2160
2161      CHARACTER(LEN=default_path_length)                 :: coupling_function
2162      CHARACTER(LEN=default_string_length)               :: def_error, this_error
2163      CHARACTER(LEN=default_string_length), &
2164         DIMENSION(:), POINTER                           :: parameters
2165      INTEGER                                            :: iatom, iforce_eval, iparticle, &
2166                                                            jparticle, natom, natom_iforce, &
2167                                                            nforce_eval
2168      INTEGER, DIMENSION(:), POINTER                     :: glob_natoms, map_index
2169      REAL(dp)                                           :: dedf, dx, err, fi(3), lerr, &
2170                                                            potential_energy
2171      REAL(KIND=dp), DIMENSION(:), POINTER               :: values
2172      TYPE(cp_subsys_p_type), DIMENSION(:), POINTER      :: subsystems
2173      TYPE(cp_subsys_type), POINTER                      :: subsys_main
2174      TYPE(mixed_force_type), DIMENSION(:), POINTER      :: global_forces
2175      TYPE(particle_list_p_type), DIMENSION(:), POINTER  :: particles
2176      TYPE(particle_list_type), POINTER                  :: particles_main
2177      TYPE(section_vals_type), POINTER                   :: force_env_section, mapping_section, &
2178                                                            wrk_section
2179
2180      IF (PRESENT(force_env)) THEN
2181         NULLIFY (particles_main, subsys_main)
2182         CALL force_env_get(force_env=force_env, subsys=subsys_main)
2183         CALL cp_subsys_get(subsys=subsys_main, particles=particles_main)
2184         natom = SIZE(particles_main%els)
2185         colvar%n_atom_s = natom
2186         colvar%u_param%natom = natom
2187         CALL reallocate(colvar%i_atom, 1, natom)
2188         CALL reallocate(colvar%dsdr, 1, 3, 1, natom)
2189         DO iatom = 1, natom
2190            colvar%i_atom(iatom) = iatom
2191         ENDDO
2192
2193         IF (.NOT. ASSOCIATED(colvar%u_param%mixed_energy_section)) THEN
2194            CALL force_env_get(force_env, potential_energy=potential_energy)
2195            colvar%ss = potential_energy
2196
2197            DO iatom = 1, natom
2198               ! store derivative
2199               fi(:) = -particles_main%els(iatom)%f
2200               CALL put_derivative(colvar, iatom, fi)
2201            ENDDO
2202         ELSE
2203            IF (force_env%in_use /= use_mixed_force) &
2204               CALL cp_abort(__LOCATION__, &
2205                             'ASSERTION (cond) failed at line '//cp_to_string(__LINE__)// &
2206                             ' A combination of mixed force_eval energies has been requested as '// &
2207                             ' collective variable, but the MIXED env is not in use! Aborting.')
2208            CALL force_env_get(force_env, force_env_section=force_env_section)
2209            mapping_section => section_vals_get_subs_vals(force_env_section, "MIXED%MAPPING")
2210            NULLIFY (values, parameters, subsystems, particles, global_forces, map_index, glob_natoms)
2211            nforce_eval = SIZE(force_env%sub_force_env)
2212            ALLOCATE (glob_natoms(nforce_eval))
2213            ALLOCATE (subsystems(nforce_eval))
2214            ALLOCATE (particles(nforce_eval))
2215            ! Local Info to sync
2216            ALLOCATE (global_forces(nforce_eval))
2217
2218            glob_natoms = 0
2219            DO iforce_eval = 1, nforce_eval
2220               NULLIFY (subsystems(iforce_eval)%subsys, particles(iforce_eval)%list)
2221               IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
2222               ! Get all available subsys
2223               CALL force_env_get(force_env=force_env%sub_force_env(iforce_eval)%force_env, &
2224                                  subsys=subsystems(iforce_eval)%subsys)
2225               ! Get available particles
2226               CALL cp_subsys_get(subsys=subsystems(iforce_eval)%subsys, &
2227                                  particles=particles(iforce_eval)%list)
2228
2229               ! Get Mapping index array
2230               natom_iforce = SIZE(particles(iforce_eval)%list%els)
2231
2232               ! Only the rank 0 process collect info for each computation
2233               IF (force_env%sub_force_env(iforce_eval)%force_env%para_env%ionode) THEN
2234                  glob_natoms(iforce_eval) = natom_iforce
2235               END IF
2236            END DO
2237
2238            ! Handling Parallel execution
2239            CALL mp_sync(force_env%para_env%group)
2240            CALL mp_sum(glob_natoms, force_env%para_env%group)
2241
2242            ! Transfer forces
2243            DO iforce_eval = 1, nforce_eval
2244               ALLOCATE (global_forces(iforce_eval)%forces(3, glob_natoms(iforce_eval)))
2245               global_forces(iforce_eval)%forces = 0.0_dp
2246               IF (ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) THEN
2247                  IF (force_env%sub_force_env(iforce_eval)%force_env%para_env%ionode) THEN
2248                     ! Forces
2249                     DO iparticle = 1, glob_natoms(iforce_eval)
2250                        global_forces(iforce_eval)%forces(:, iparticle) = &
2251                           particles(iforce_eval)%list%els(iparticle)%f
2252                     END DO
2253                  END IF
2254               END IF
2255               CALL mp_sum(global_forces(iforce_eval)%forces, force_env%para_env%group)
2256            END DO
2257
2258            wrk_section => colvar%u_param%mixed_energy_section
2259            ! Support any number of force_eval sections
2260            CALL get_generic_info(wrk_section, "ENERGY_FUNCTION", coupling_function, parameters, &
2261                                  values, force_env%mixed_env%energies)
2262            CALL initf(1)
2263            CALL parsef(1, TRIM(coupling_function), parameters)
2264            ! Store the value of the COLVAR
2265            colvar%ss = evalf(1, values)
2266            CPASSERT(EvalErrType <= 0)
2267
2268            DO iforce_eval = 1, nforce_eval
2269               CALL section_vals_val_get(wrk_section, "DX", r_val=dx)
2270               CALL section_vals_val_get(wrk_section, "ERROR_LIMIT", r_val=lerr)
2271               dedf = evalfd(1, iforce_eval, values, dx, err)
2272               IF (ABS(err) > lerr) THEN
2273                  WRITE (this_error, "(A,G12.6,A)") "(", err, ")"
2274                  WRITE (def_error, "(A,G12.6,A)") "(", lerr, ")"
2275                  CALL compress(this_error, .TRUE.)
2276                  CALL compress(def_error, .TRUE.)
2277                  CALL cp_warn(__LOCATION__, &
2278                               'ASSERTION (cond) failed at line '//cp_to_string(__LINE__)// &
2279                               ' Error '//TRIM(this_error)//' in computing numerical derivatives larger then'// &
2280                               TRIM(def_error)//' .')
2281               END IF
2282               ! General Mapping of forces...
2283               ! First: Get Mapping index array
2284               CALL get_subsys_map_index(mapping_section, glob_natoms(iforce_eval), iforce_eval, &
2285                                         nforce_eval, map_index)
2286
2287               ! Second: store derivatives
2288               DO iparticle = 1, glob_natoms(iforce_eval)
2289                  jparticle = map_index(iparticle)
2290                  fi = -dedf*global_forces(iforce_eval)%forces(:, iparticle)
2291                  CALL put_derivative(colvar, jparticle, fi)
2292               END DO
2293               ! Deallocate map_index array
2294               IF (ASSOCIATED(map_index)) THEN
2295                  DEALLOCATE (map_index)
2296               END IF
2297            END DO
2298            CALL finalizef()
2299            DO iforce_eval = 1, nforce_eval
2300               DEALLOCATE (global_forces(iforce_eval)%forces)
2301            END DO
2302            DEALLOCATE (glob_natoms)
2303            DEALLOCATE (values)
2304            DEALLOCATE (parameters)
2305            DEALLOCATE (global_forces)
2306            DEALLOCATE (subsystems)
2307            DEALLOCATE (particles)
2308         END IF
2309      ELSE
2310         CPABORT("need force_env!")
2311      ENDIF
2312   END SUBROUTINE u_colvar
2313
2314! **************************************************************************************************
2315!> \brief evaluates the force due (and on) the distance from the plane collective variable
2316!> \param colvar ...
2317!> \param cell ...
2318!> \param subsys ...
2319!> \param particles ...
2320!> \author Teodoro Laino 02.2006 [created]
2321! **************************************************************************************************
2322   SUBROUTINE plane_distance_colvar(colvar, cell, subsys, particles)
2323
2324      TYPE(colvar_type), POINTER                         :: colvar
2325      TYPE(cell_type), POINTER                           :: cell
2326      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
2327      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
2328         POINTER                                         :: particles
2329
2330      CHARACTER(len=*), PARAMETER :: routineN = 'plane_distance_colvar', &
2331         routineP = moduleN//':'//routineN
2332
2333      INTEGER                                            :: i, j, k, l
2334      REAL(dp) :: a, b, dsdxpn(3), dxpndxi(3, 3), dxpndxj(3, 3), dxpndxk(3, 3), fi(3), fj(3), &
2335         fk(3), fl(3), r12, ri(3), rj(3), rk(3), rl(3), ss(3), xpij(3), xpkj(3), xpl(3), xpn(3)
2336      TYPE(particle_list_type), POINTER                  :: particles_i
2337      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
2338
2339      NULLIFY (particles_i)
2340
2341      CPASSERT(colvar%type_id == plane_distance_colvar_id)
2342      IF (PRESENT(particles)) THEN
2343         my_particles => particles
2344      ELSE
2345         CPASSERT(PRESENT(subsys))
2346         CALL cp_subsys_get(subsys, particles=particles_i)
2347         my_particles => particles_i%els
2348      END IF
2349      i = colvar%plane_distance_param%plane(1)
2350      j = colvar%plane_distance_param%plane(2)
2351      k = colvar%plane_distance_param%plane(3)
2352      l = colvar%plane_distance_param%point
2353      ! Get coordinates of atoms or points
2354      CALL get_coordinates(colvar, i, ri, my_particles)
2355      CALL get_coordinates(colvar, j, rj, my_particles)
2356      CALL get_coordinates(colvar, k, rk, my_particles)
2357      CALL get_coordinates(colvar, l, rl, my_particles)
2358      xpij = ri - rj
2359      xpkj = rk - rj
2360      xpl = rl - (ri + rj + rk)/3.0_dp
2361      IF (colvar%plane_distance_param%use_pbc) THEN
2362         ! xpij
2363         ss = MATMUL(cell%h_inv, ri - rj)
2364         ss = ss - NINT(ss)
2365         xpij = MATMUL(cell%hmat, ss)
2366         ! xpkj
2367         ss = MATMUL(cell%h_inv, rk - rj)
2368         ss = ss - NINT(ss)
2369         xpkj = MATMUL(cell%hmat, ss)
2370         ! xpl
2371         ss = MATMUL(cell%h_inv, rl - (ri + rj + rk)/3.0_dp)
2372         ss = ss - NINT(ss)
2373         xpl = MATMUL(cell%hmat, ss)
2374      END IF
2375      ! xpn
2376      xpn(1) = xpij(2)*xpkj(3) - xpij(3)*xpkj(2)
2377      xpn(2) = xpij(3)*xpkj(1) - xpij(1)*xpkj(3)
2378      xpn(3) = xpij(1)*xpkj(2) - xpij(2)*xpkj(1)
2379      a = DOT_PRODUCT(xpn, xpn)
2380      b = DOT_PRODUCT(xpl, xpn)
2381      r12 = SQRT(a)
2382      colvar%ss = b/r12
2383      dsdxpn(1) = xpl(1)/r12 - b*xpn(1)/(r12*a)
2384      dsdxpn(2) = xpl(2)/r12 - b*xpn(2)/(r12*a)
2385      dsdxpn(3) = xpl(3)/r12 - b*xpn(3)/(r12*a)
2386      !
2387      dxpndxi(1, 1) = 0.0_dp
2388      dxpndxi(1, 2) = 1.0_dp*xpkj(3)
2389      dxpndxi(1, 3) = -1.0_dp*xpkj(2)
2390      dxpndxi(2, 1) = -1.0_dp*xpkj(3)
2391      dxpndxi(2, 2) = 0.0_dp
2392      dxpndxi(2, 3) = 1.0_dp*xpkj(1)
2393      dxpndxi(3, 1) = 1.0_dp*xpkj(2)
2394      dxpndxi(3, 2) = -1.0_dp*xpkj(1)
2395      dxpndxi(3, 3) = 0.0_dp
2396      !
2397      dxpndxj(1, 1) = 0.0_dp
2398      dxpndxj(1, 2) = -1.0_dp*xpkj(3) + xpij(3)
2399      dxpndxj(1, 3) = -1.0_dp*xpij(2) + xpkj(2)
2400      dxpndxj(2, 1) = -1.0_dp*xpij(3) + xpkj(3)
2401      dxpndxj(2, 2) = 0.0_dp
2402      dxpndxj(2, 3) = -1.0_dp*xpkj(1) + xpij(1)
2403      dxpndxj(3, 1) = -1.0_dp*xpkj(2) + xpij(2)
2404      dxpndxj(3, 2) = -1.0_dp*xpij(1) + xpkj(1)
2405      dxpndxj(3, 3) = 0.0_dp
2406      !
2407      dxpndxk(1, 1) = 0.0_dp
2408      dxpndxk(1, 2) = -1.0_dp*xpij(3)
2409      dxpndxk(1, 3) = 1.0_dp*xpij(2)
2410      dxpndxk(2, 1) = 1.0_dp*xpij(3)
2411      dxpndxk(2, 2) = 0.0_dp
2412      dxpndxk(2, 3) = -1.0_dp*xpij(1)
2413      dxpndxk(3, 1) = -1.0_dp*xpij(2)
2414      dxpndxk(3, 2) = 1.0_dp*xpij(1)
2415      dxpndxk(3, 3) = 0.0_dp
2416      !
2417      fi(:) = MATMUL(dsdxpn, dxpndxi) - xpn/(3.0_dp*r12)
2418      fj(:) = MATMUL(dsdxpn, dxpndxj) - xpn/(3.0_dp*r12)
2419      fk(:) = MATMUL(dsdxpn, dxpndxk) - xpn/(3.0_dp*r12)
2420      fl(:) = xpn/r12
2421      ! Transfer derivatives on atoms
2422      CALL put_derivative(colvar, 1, fi)
2423      CALL put_derivative(colvar, 2, fj)
2424      CALL put_derivative(colvar, 3, fk)
2425      CALL put_derivative(colvar, 4, fl)
2426
2427   END SUBROUTINE plane_distance_colvar
2428
2429! **************************************************************************************************
2430!> \brief evaluates the force due (and on) the angle between two planes.
2431!>        plane-plane angle collective variable
2432!> \param colvar ...
2433!> \param cell ...
2434!> \param subsys ...
2435!> \param particles ...
2436!> \author Teodoro Laino 02.2009 [created]
2437! **************************************************************************************************
2438   SUBROUTINE plane_plane_angle_colvar(colvar, cell, subsys, particles)
2439
2440      TYPE(colvar_type), POINTER                         :: colvar
2441      TYPE(cell_type), POINTER                           :: cell
2442      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
2443      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
2444         POINTER                                         :: particles
2445
2446      CHARACTER(len=*), PARAMETER :: routineN = 'plane_plane_angle_colvar', &
2447         routineP = moduleN//':'//routineN
2448
2449      INTEGER                                            :: i1, i2, j1, j2, k1, k2, np
2450      LOGICAL                                            :: check
2451      REAL(dp) :: a1, a2, d, dnorm_dxpn(3), dprod12_dxpn(3), dsdxpn(3), dt_dxpn(3), dxpndxi(3, 3), &
2452         dxpndxj(3, 3), dxpndxk(3, 3), fi(3), fj(3), fk(3), fmod, norm1, norm2, prod_12, ri1(3), &
2453         ri2(3), rj1(3), rj2(3), rk1(3), rk2(3), ss(3), t, xpij1(3), xpij2(3), xpkj1(3), xpkj2(3), &
2454         xpn1(3), xpn2(3)
2455      TYPE(particle_list_type), POINTER                  :: particles_i
2456      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
2457
2458      NULLIFY (particles_i)
2459
2460      check = colvar%type_id == plane_plane_angle_colvar_id
2461      CPASSERT(check)
2462      IF (PRESENT(particles)) THEN
2463         my_particles => particles
2464      ELSE
2465         CPASSERT(PRESENT(subsys))
2466         CALL cp_subsys_get(subsys, particles=particles_i)
2467         my_particles => particles_i%els
2468      END IF
2469
2470      ! Plane 1
2471      IF (colvar%plane_plane_angle_param%plane1%type_of_def == plane_def_atoms) THEN
2472         i1 = colvar%plane_plane_angle_param%plane1%points(1)
2473         j1 = colvar%plane_plane_angle_param%plane1%points(2)
2474         k1 = colvar%plane_plane_angle_param%plane1%points(3)
2475
2476         ! Get coordinates of atoms or points
2477         CALL get_coordinates(colvar, i1, ri1, my_particles)
2478         CALL get_coordinates(colvar, j1, rj1, my_particles)
2479         CALL get_coordinates(colvar, k1, rk1, my_particles)
2480
2481         ! xpij
2482         ss = MATMUL(cell%h_inv, ri1 - rj1)
2483         ss = ss - NINT(ss)
2484         xpij1 = MATMUL(cell%hmat, ss)
2485
2486         ! xpkj
2487         ss = MATMUL(cell%h_inv, rk1 - rj1)
2488         ss = ss - NINT(ss)
2489         xpkj1 = MATMUL(cell%hmat, ss)
2490
2491         ! xpn
2492         xpn1(1) = xpij1(2)*xpkj1(3) - xpij1(3)*xpkj1(2)
2493         xpn1(2) = xpij1(3)*xpkj1(1) - xpij1(1)*xpkj1(3)
2494         xpn1(3) = xpij1(1)*xpkj1(2) - xpij1(2)*xpkj1(1)
2495      ELSE
2496         xpn1 = colvar%plane_plane_angle_param%plane1%normal_vec
2497      END IF
2498      a1 = DOT_PRODUCT(xpn1, xpn1)
2499      norm1 = SQRT(a1)
2500      CPASSERT(norm1 /= 0.0_dp)
2501
2502      ! Plane 2
2503      IF (colvar%plane_plane_angle_param%plane2%type_of_def == plane_def_atoms) THEN
2504         i2 = colvar%plane_plane_angle_param%plane2%points(1)
2505         j2 = colvar%plane_plane_angle_param%plane2%points(2)
2506         k2 = colvar%plane_plane_angle_param%plane2%points(3)
2507
2508         ! Get coordinates of atoms or points
2509         CALL get_coordinates(colvar, i2, ri2, my_particles)
2510         CALL get_coordinates(colvar, j2, rj2, my_particles)
2511         CALL get_coordinates(colvar, k2, rk2, my_particles)
2512
2513         ! xpij
2514         ss = MATMUL(cell%h_inv, ri2 - rj2)
2515         ss = ss - NINT(ss)
2516         xpij2 = MATMUL(cell%hmat, ss)
2517
2518         ! xpkj
2519         ss = MATMUL(cell%h_inv, rk2 - rj2)
2520         ss = ss - NINT(ss)
2521         xpkj2 = MATMUL(cell%hmat, ss)
2522
2523         ! xpn
2524         xpn2(1) = xpij2(2)*xpkj2(3) - xpij2(3)*xpkj2(2)
2525         xpn2(2) = xpij2(3)*xpkj2(1) - xpij2(1)*xpkj2(3)
2526         xpn2(3) = xpij2(1)*xpkj2(2) - xpij2(2)*xpkj2(1)
2527      ELSE
2528         xpn2 = colvar%plane_plane_angle_param%plane2%normal_vec
2529      END IF
2530      a2 = DOT_PRODUCT(xpn2, xpn2)
2531      norm2 = SQRT(a2)
2532      CPASSERT(norm2 /= 0.0_dp)
2533
2534      ! The value of the angle is defined only between 0 and Pi
2535      prod_12 = DOT_PRODUCT(xpn1, xpn2)
2536
2537      d = norm1*norm2
2538      t = prod_12/d
2539      t = MIN(1.0_dp, ABS(t))*SIGN(1.0_dp, t)
2540      colvar%ss = ACOS(t)
2541
2542      IF ((ABS(colvar%ss) .LT. tolerance_acos) .OR. (ABS(colvar%ss - pi) .LT. tolerance_acos)) THEN
2543         fmod = 0.0_dp
2544      ELSE
2545         fmod = -1.0_dp/SIN(colvar%ss)
2546      ENDIF
2547      ! Compute derivatives
2548      np = 0
2549      ! Plane 1
2550      IF (colvar%plane_plane_angle_param%plane1%type_of_def == plane_def_atoms) THEN
2551         dprod12_dxpn = xpn2
2552         dnorm_dxpn = 1.0_dp/norm1*xpn1
2553         dt_dxpn = (dprod12_dxpn*d - prod_12*dnorm_dxpn*norm2)/d**2
2554
2555         dsdxpn(1) = fmod*dt_dxpn(1)
2556         dsdxpn(2) = fmod*dt_dxpn(2)
2557         dsdxpn(3) = fmod*dt_dxpn(3)
2558         !
2559         dxpndxi(1, 1) = 0.0_dp
2560         dxpndxi(1, 2) = 1.0_dp*xpkj1(3)
2561         dxpndxi(1, 3) = -1.0_dp*xpkj1(2)
2562         dxpndxi(2, 1) = -1.0_dp*xpkj1(3)
2563         dxpndxi(2, 2) = 0.0_dp
2564         dxpndxi(2, 3) = 1.0_dp*xpkj1(1)
2565         dxpndxi(3, 1) = 1.0_dp*xpkj1(2)
2566         dxpndxi(3, 2) = -1.0_dp*xpkj1(1)
2567         dxpndxi(3, 3) = 0.0_dp
2568         !
2569         dxpndxj(1, 1) = 0.0_dp
2570         dxpndxj(1, 2) = -1.0_dp*xpkj1(3) + xpij1(3)
2571         dxpndxj(1, 3) = -1.0_dp*xpij1(2) + xpkj1(2)
2572         dxpndxj(2, 1) = -1.0_dp*xpij1(3) + xpkj1(3)
2573         dxpndxj(2, 2) = 0.0_dp
2574         dxpndxj(2, 3) = -1.0_dp*xpkj1(1) + xpij1(1)
2575         dxpndxj(3, 1) = -1.0_dp*xpkj1(2) + xpij1(2)
2576         dxpndxj(3, 2) = -1.0_dp*xpij1(1) + xpkj1(1)
2577         dxpndxj(3, 3) = 0.0_dp
2578         !
2579         dxpndxk(1, 1) = 0.0_dp
2580         dxpndxk(1, 2) = -1.0_dp*xpij1(3)
2581         dxpndxk(1, 3) = 1.0_dp*xpij1(2)
2582         dxpndxk(2, 1) = 1.0_dp*xpij1(3)
2583         dxpndxk(2, 2) = 0.0_dp
2584         dxpndxk(2, 3) = -1.0_dp*xpij1(1)
2585         dxpndxk(3, 1) = -1.0_dp*xpij1(2)
2586         dxpndxk(3, 2) = 1.0_dp*xpij1(1)
2587         dxpndxk(3, 3) = 0.0_dp
2588         !
2589         fi = MATMUL(dsdxpn, dxpndxi)
2590         fj = MATMUL(dsdxpn, dxpndxj)
2591         fk = MATMUL(dsdxpn, dxpndxk)
2592
2593         ! Transfer derivatives on atoms
2594         CALL put_derivative(colvar, np + 1, fi)
2595         CALL put_derivative(colvar, np + 2, fj)
2596         CALL put_derivative(colvar, np + 3, fk)
2597         np = 3
2598      END IF
2599
2600      ! Plane 2
2601      IF (colvar%plane_plane_angle_param%plane2%type_of_def == plane_def_atoms) THEN
2602         dprod12_dxpn = xpn1
2603         dnorm_dxpn = 1.0_dp/norm2*xpn2
2604         dt_dxpn = (dprod12_dxpn*d - prod_12*dnorm_dxpn*norm1)/d**2
2605
2606         dsdxpn(1) = fmod*dt_dxpn(1)
2607         dsdxpn(2) = fmod*dt_dxpn(2)
2608         dsdxpn(3) = fmod*dt_dxpn(3)
2609         !
2610         dxpndxi(1, 1) = 0.0_dp
2611         dxpndxi(1, 2) = 1.0_dp*xpkj1(3)
2612         dxpndxi(1, 3) = -1.0_dp*xpkj1(2)
2613         dxpndxi(2, 1) = -1.0_dp*xpkj1(3)
2614         dxpndxi(2, 2) = 0.0_dp
2615         dxpndxi(2, 3) = 1.0_dp*xpkj1(1)
2616         dxpndxi(3, 1) = 1.0_dp*xpkj1(2)
2617         dxpndxi(3, 2) = -1.0_dp*xpkj1(1)
2618         dxpndxi(3, 3) = 0.0_dp
2619         !
2620         dxpndxj(1, 1) = 0.0_dp
2621         dxpndxj(1, 2) = -1.0_dp*xpkj1(3) + xpij1(3)
2622         dxpndxj(1, 3) = -1.0_dp*xpij1(2) + xpkj1(2)
2623         dxpndxj(2, 1) = -1.0_dp*xpij1(3) + xpkj1(3)
2624         dxpndxj(2, 2) = 0.0_dp
2625         dxpndxj(2, 3) = -1.0_dp*xpkj1(1) + xpij1(1)
2626         dxpndxj(3, 1) = -1.0_dp*xpkj1(2) + xpij1(2)
2627         dxpndxj(3, 2) = -1.0_dp*xpij1(1) + xpkj1(1)
2628         dxpndxj(3, 3) = 0.0_dp
2629         !
2630         dxpndxk(1, 1) = 0.0_dp
2631         dxpndxk(1, 2) = -1.0_dp*xpij1(3)
2632         dxpndxk(1, 3) = 1.0_dp*xpij1(2)
2633         dxpndxk(2, 1) = 1.0_dp*xpij1(3)
2634         dxpndxk(2, 2) = 0.0_dp
2635         dxpndxk(2, 3) = -1.0_dp*xpij1(1)
2636         dxpndxk(3, 1) = -1.0_dp*xpij1(2)
2637         dxpndxk(3, 2) = 1.0_dp*xpij1(1)
2638         dxpndxk(3, 3) = 0.0_dp
2639         !
2640         fi = MATMUL(dsdxpn, dxpndxi)
2641         fj = MATMUL(dsdxpn, dxpndxj)
2642         fk = MATMUL(dsdxpn, dxpndxk)
2643
2644         ! Transfer derivatives on atoms
2645         CALL put_derivative(colvar, np + 1, fi)
2646         CALL put_derivative(colvar, np + 2, fj)
2647         CALL put_derivative(colvar, np + 3, fk)
2648      END IF
2649
2650   END SUBROUTINE plane_plane_angle_colvar
2651
2652! **************************************************************************************************
2653!> \brief Evaluates the value of the rotation angle between two bonds
2654!> \param colvar ...
2655!> \param cell ...
2656!> \param subsys ...
2657!> \param particles ...
2658!> \author Teodoro Laino 02.2006 [created]
2659! **************************************************************************************************
2660   SUBROUTINE rotation_colvar(colvar, cell, subsys, particles)
2661      TYPE(colvar_type), POINTER                         :: colvar
2662      TYPE(cell_type), POINTER                           :: cell
2663      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
2664      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
2665         POINTER                                         :: particles
2666
2667      CHARACTER(len=*), PARAMETER :: routineN = 'rotation_colvar', &
2668         routineP = moduleN//':'//routineN
2669
2670      INTEGER                                            :: i, idum
2671      REAL(dp)                                           :: a, b, fmod, t0, t1, t2, t3, xdum(3), &
2672                                                            xij(3), xkj(3)
2673      REAL(KIND=dp)                                      :: dp1b1(3), dp1b2(3), dp2b1(3), dp2b2(3), &
2674                                                            ss(3), xp1b1(3), xp1b2(3), xp2b1(3), &
2675                                                            xp2b2(3)
2676      TYPE(particle_list_type), POINTER                  :: particles_i
2677      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
2678
2679      NULLIFY (particles_i)
2680
2681      CPASSERT(colvar%type_id == rotation_colvar_id)
2682      IF (PRESENT(particles)) THEN
2683         my_particles => particles
2684      ELSE
2685         CPASSERT(PRESENT(subsys))
2686         CALL cp_subsys_get(subsys, particles=particles_i)
2687         my_particles => particles_i%els
2688      END IF
2689      i = colvar%rotation_param%i_at1_bond1
2690      CALL get_coordinates(colvar, i, xp1b1, my_particles)
2691      i = colvar%rotation_param%i_at2_bond1
2692      CALL get_coordinates(colvar, i, xp2b1, my_particles)
2693      i = colvar%rotation_param%i_at1_bond2
2694      CALL get_coordinates(colvar, i, xp1b2, my_particles)
2695      i = colvar%rotation_param%i_at2_bond2
2696      CALL get_coordinates(colvar, i, xp2b2, my_particles)
2697      ! xij
2698      ss = MATMUL(cell%h_inv, xp1b1 - xp2b1)
2699      ss = ss - NINT(ss)
2700      xij = MATMUL(cell%hmat, ss)
2701      ! xkj
2702      ss = MATMUL(cell%h_inv, xp1b2 - xp2b2)
2703      ss = ss - NINT(ss)
2704      xkj = MATMUL(cell%hmat, ss)
2705      ! evaluation of the angle..
2706      a = SQRT(DOT_PRODUCT(xij, xij))
2707      b = SQRT(DOT_PRODUCT(xkj, xkj))
2708      t0 = 1.0_dp/(a*b)
2709      t1 = 1.0_dp/(a**3.0_dp*b)
2710      t2 = 1.0_dp/(a*b**3.0_dp)
2711      t3 = DOT_PRODUCT(xij, xkj)
2712      colvar%ss = ACOS(t3*t0)
2713      IF ((ABS(colvar%ss) .LT. tolerance_acos) .OR. (ABS(colvar%ss - pi) .LT. tolerance_acos)) THEN
2714         fmod = 0.0_dp
2715      ELSE
2716         fmod = -1.0_dp/SIN(colvar%ss)
2717      ENDIF
2718      dp1b1 = xkj(:)*t0 - xij(:)*t1*t3
2719      dp2b1 = -xkj(:)*t0 + xij(:)*t1*t3
2720      dp1b2 = xij(:)*t0 - xkj(:)*t2*t3
2721      dp2b2 = -xij(:)*t0 + xkj(:)*t2*t3
2722
2723      xdum = dp1b1*fmod
2724      idum = colvar%rotation_param%i_at1_bond1
2725      CALL put_derivative(colvar, idum, xdum)
2726      xdum = dp2b1*fmod
2727      idum = colvar%rotation_param%i_at2_bond1
2728      CALL put_derivative(colvar, idum, xdum)
2729      xdum = dp1b2*fmod
2730      idum = colvar%rotation_param%i_at1_bond2
2731      CALL put_derivative(colvar, idum, xdum)
2732      xdum = dp2b2*fmod
2733      idum = colvar%rotation_param%i_at2_bond2
2734      CALL put_derivative(colvar, idum, xdum)
2735
2736   END SUBROUTINE rotation_colvar
2737
2738! **************************************************************************************************
2739!> \brief evaluates the force due to the function of two distances
2740!> \param colvar ...
2741!> \param cell ...
2742!> \param subsys ...
2743!> \param particles ...
2744!> \author Teodoro Laino 02.2006 [created]
2745!> \note modified Florian Schiffmann 08.2008
2746! **************************************************************************************************
2747   SUBROUTINE dfunct_colvar(colvar, cell, subsys, particles)
2748      TYPE(colvar_type), POINTER                         :: colvar
2749      TYPE(cell_type), POINTER                           :: cell
2750      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
2751      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
2752         POINTER                                         :: particles
2753
2754      CHARACTER(len=*), PARAMETER :: routineN = 'dfunct_colvar', routineP = moduleN//':'//routineN
2755
2756      INTEGER                                            :: i, j, k, l
2757      REAL(dp)                                           :: fi(3), fj(3), fk(3), fl(3), r12, r34, &
2758                                                            ss(3), xij(3), xkl(3), xpi(3), xpj(3), &
2759                                                            xpk(3), xpl(3)
2760      TYPE(particle_list_type), POINTER                  :: particles_i
2761      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
2762
2763      NULLIFY (particles_i)
2764
2765      CPASSERT(colvar%type_id == dfunct_colvar_id)
2766      IF (PRESENT(particles)) THEN
2767         my_particles => particles
2768      ELSE
2769         CPASSERT(PRESENT(subsys))
2770         CALL cp_subsys_get(subsys, particles=particles_i)
2771         my_particles => particles_i%els
2772      END IF
2773      i = colvar%dfunct_param%i_at_dfunct(1)
2774      j = colvar%dfunct_param%i_at_dfunct(2)
2775      ! First bond
2776      CALL get_coordinates(colvar, i, xpi, my_particles)
2777      CALL get_coordinates(colvar, j, xpj, my_particles)
2778      IF (colvar%dfunct_param%use_pbc) THEN
2779         ss = MATMUL(cell%h_inv, xpi - xpj)
2780         ss = ss - NINT(ss)
2781         xij = MATMUL(cell%hmat, ss)
2782      ELSE
2783         xij = xpi - xpj
2784      END IF
2785      r12 = SQRT(xij(1)**2 + xij(2)**2 + xij(3)**2)
2786      ! Second bond
2787      k = colvar%dfunct_param%i_at_dfunct(3)
2788      l = colvar%dfunct_param%i_at_dfunct(4)
2789      CALL get_coordinates(colvar, k, xpk, my_particles)
2790      CALL get_coordinates(colvar, l, xpl, my_particles)
2791      IF (colvar%dfunct_param%use_pbc) THEN
2792         ss = MATMUL(cell%h_inv, xpk - xpl)
2793         ss = ss - NINT(ss)
2794         xkl = MATMUL(cell%hmat, ss)
2795      ELSE
2796         xkl = xpk - xpl
2797      END IF
2798      r34 = SQRT(xkl(1)**2 + xkl(2)**2 + xkl(3)**2)
2799      !
2800      colvar%ss = r12 + colvar%dfunct_param%coeff*r34
2801      fi(:) = xij/r12
2802      fj(:) = -xij/r12
2803      fk(:) = colvar%dfunct_param%coeff*xkl/r34
2804      fl(:) = -colvar%dfunct_param%coeff*xkl/r34
2805      CALL put_derivative(colvar, 1, fi)
2806      CALL put_derivative(colvar, 2, fj)
2807      CALL put_derivative(colvar, 3, fk)
2808      CALL put_derivative(colvar, 4, fl)
2809
2810   END SUBROUTINE dfunct_colvar
2811
2812! **************************************************************************************************
2813!> \brief evaluates the force due (and on) the distance from the plane collective variable
2814!> \param colvar ...
2815!> \param cell ...
2816!> \param subsys ...
2817!> \param particles ...
2818!> \author Teodoro Laino 02.2006 [created]
2819! **************************************************************************************************
2820   SUBROUTINE angle_colvar(colvar, cell, subsys, particles)
2821      TYPE(colvar_type), POINTER                         :: colvar
2822      TYPE(cell_type), POINTER                           :: cell
2823      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
2824      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
2825         POINTER                                         :: particles
2826
2827      CHARACTER(len=*), PARAMETER :: routineN = 'angle_colvar', routineP = moduleN//':'//routineN
2828
2829      INTEGER                                            :: i, j, k
2830      REAL(dp)                                           :: a, b, fi(3), fj(3), fk(3), fmod, ri(3), &
2831                                                            rj(3), rk(3), ss(3), t0, t1, t2, t3, &
2832                                                            xij(3), xkj(3)
2833      TYPE(particle_list_type), POINTER                  :: particles_i
2834      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
2835
2836      NULLIFY (particles_i)
2837
2838      CPASSERT(colvar%type_id == angle_colvar_id)
2839      IF (PRESENT(particles)) THEN
2840         my_particles => particles
2841      ELSE
2842         CPASSERT(PRESENT(subsys))
2843         CALL cp_subsys_get(subsys, particles=particles_i)
2844         my_particles => particles_i%els
2845      END IF
2846      i = colvar%angle_param%i_at_angle(1)
2847      j = colvar%angle_param%i_at_angle(2)
2848      k = colvar%angle_param%i_at_angle(3)
2849      CALL get_coordinates(colvar, i, ri, my_particles)
2850      CALL get_coordinates(colvar, j, rj, my_particles)
2851      CALL get_coordinates(colvar, k, rk, my_particles)
2852      ! xij
2853      ss = MATMUL(cell%h_inv, ri - rj)
2854      ss = ss - NINT(ss)
2855      xij = MATMUL(cell%hmat, ss)
2856      ! xkj
2857      ss = MATMUL(cell%h_inv, rk - rj)
2858      ss = ss - NINT(ss)
2859      xkj = MATMUL(cell%hmat, ss)
2860      ! Evaluation of the angle..
2861      a = SQRT(DOT_PRODUCT(xij, xij))
2862      b = SQRT(DOT_PRODUCT(xkj, xkj))
2863      t0 = 1.0_dp/(a*b)
2864      t1 = 1.0_dp/(a**3.0_dp*b)
2865      t2 = 1.0_dp/(a*b**3.0_dp)
2866      t3 = DOT_PRODUCT(xij, xkj)
2867      colvar%ss = ACOS(t3*t0)
2868      IF ((ABS(colvar%ss) .LT. tolerance_acos) .OR. (ABS(colvar%ss - pi) .LT. tolerance_acos)) THEN
2869         fmod = 0.0_dp
2870      ELSE
2871         fmod = -1.0_dp/SIN(colvar%ss)
2872      ENDIF
2873      fi(:) = xkj(:)*t0 - xij(:)*t1*t3
2874      fj(:) = -xkj(:)*t0 + xij(:)*t1*t3 - xij(:)*t0 + xkj(:)*t2*t3
2875      fk(:) = xij(:)*t0 - xkj(:)*t2*t3
2876      fi = fi*fmod
2877      fj = fj*fmod
2878      fk = fk*fmod
2879      CALL put_derivative(colvar, 1, fi)
2880      CALL put_derivative(colvar, 2, fj)
2881      CALL put_derivative(colvar, 3, fk)
2882
2883   END SUBROUTINE angle_colvar
2884
2885! **************************************************************************************************
2886!> \brief evaluates the force due (and on) the distance collective variable
2887!> \param colvar ...
2888!> \param cell ...
2889!> \param subsys ...
2890!> \param particles ...
2891!> \author Alessandro Laio, Fawzi Mohamed
2892! **************************************************************************************************
2893   SUBROUTINE dist_colvar(colvar, cell, subsys, particles)
2894      TYPE(colvar_type), POINTER                         :: colvar
2895      TYPE(cell_type), POINTER                           :: cell
2896      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
2897      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
2898         POINTER                                         :: particles
2899
2900      CHARACTER(len=*), PARAMETER :: routineN = 'dist_colvar', routineP = moduleN//':'//routineN
2901
2902      INTEGER                                            :: i, j
2903      REAL(dp)                                           :: fi(3), fj(3), r12, ss(3), xij(3), &
2904                                                            xpi(3), xpj(3)
2905      TYPE(particle_list_type), POINTER                  :: particles_i
2906      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
2907
2908      NULLIFY (particles_i)
2909
2910      CPASSERT(colvar%type_id == dist_colvar_id)
2911      IF (PRESENT(particles)) THEN
2912         my_particles => particles
2913      ELSE
2914         CPASSERT(PRESENT(subsys))
2915         CALL cp_subsys_get(subsys, particles=particles_i)
2916         my_particles => particles_i%els
2917      END IF
2918      i = colvar%dist_param%i_at
2919      j = colvar%dist_param%j_at
2920      CALL get_coordinates(colvar, i, xpi, my_particles)
2921      CALL get_coordinates(colvar, j, xpj, my_particles)
2922      ss = MATMUL(cell%h_inv, xpi - xpj)
2923      ss = ss - NINT(ss)
2924      xij = MATMUL(cell%hmat, ss)
2925      SELECT CASE (colvar%dist_param%axis_id)
2926      CASE (do_clv_x)
2927         xij(2) = 0.0_dp
2928         xij(3) = 0.0_dp
2929      CASE (do_clv_y)
2930         xij(1) = 0.0_dp
2931         xij(3) = 0.0_dp
2932      CASE (do_clv_z)
2933         xij(1) = 0.0_dp
2934         xij(2) = 0.0_dp
2935      CASE (do_clv_xy)
2936         xij(3) = 0.0_dp
2937      CASE (do_clv_xz)
2938         xij(2) = 0.0_dp
2939      CASE (do_clv_yz)
2940         xij(1) = 0.0_dp
2941      CASE DEFAULT
2942         !do_clv_xyz
2943      END SELECT
2944      r12 = SQRT(xij(1)**2 + xij(2)**2 + xij(3)**2)
2945
2946      colvar%ss = r12
2947      fi(:) = xij/r12
2948      fj(:) = -xij/r12
2949
2950      CALL put_derivative(colvar, 1, fi)
2951      CALL put_derivative(colvar, 2, fj)
2952
2953   END SUBROUTINE dist_colvar
2954
2955! **************************************************************************************************
2956!> \brief evaluates the force due to the torsion collective variable
2957!> \param colvar ...
2958!> \param cell ...
2959!> \param subsys ...
2960!> \param particles ...
2961!> \param no_riemann_sheet_op ...
2962!> \author Alessandro Laio, Fawzi Mohamed
2963! **************************************************************************************************
2964   SUBROUTINE torsion_colvar(colvar, cell, subsys, particles, no_riemann_sheet_op)
2965
2966      TYPE(colvar_type), POINTER                         :: colvar
2967      TYPE(cell_type), POINTER                           :: cell
2968      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
2969      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
2970         POINTER                                         :: particles
2971      LOGICAL, INTENT(IN), OPTIONAL                      :: no_riemann_sheet_op
2972
2973      CHARACTER(len=*), PARAMETER :: routineN = 'torsion_colvar', routineP = moduleN//':'//routineN
2974
2975      INTEGER                                            :: i, ii
2976      LOGICAL                                            :: no_riemann_sheet
2977      REAL(dp) :: angle, cosine, dedphi, dedxia, dedxib, dedxic, dedxid, dedxt, dedxu, dedyia, &
2978         dedyib, dedyic, dedyid, dedyt, dedyu, dedzia, dedzib, dedzic, dedzid, dedzt, dedzu, dt, &
2979         e, ftmp(3), o0, rcb, rt2, rtmp(3), rtru, ru2, sine, ss(3), xba, xca, xcb, xdb, xdc, xt, &
2980         xtu, xu, yba, yca, ycb, ydb, ydc, yt, ytu, yu, zba, zca, zcb, zdb, zdc, zt, ztu, zu
2981      REAL(dp), DIMENSION(3, 4)                          :: rr
2982      TYPE(particle_list_type), POINTER                  :: particles_i
2983      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
2984
2985      NULLIFY (particles_i)
2986      CPASSERT(colvar%type_id == torsion_colvar_id)
2987      IF (PRESENT(particles)) THEN
2988         my_particles => particles
2989      ELSE
2990         CPASSERT(PRESENT(subsys))
2991         CALL cp_subsys_get(subsys, particles=particles_i)
2992         my_particles => particles_i%els
2993      END IF
2994      no_riemann_sheet = .FALSE.
2995      IF (PRESENT(no_riemann_sheet_op)) no_riemann_sheet = no_riemann_sheet_op
2996      DO ii = 1, 4
2997         i = colvar%torsion_param%i_at_tors(ii)
2998         CALL get_coordinates(colvar, i, rtmp, my_particles)
2999         rr(:, ii) = rtmp(1:3)
3000      ENDDO
3001      o0 = colvar%torsion_param%o0
3002      ! ba
3003      ss = MATMUL(cell%h_inv, rr(:, 2) - rr(:, 1))
3004      ss = ss - NINT(ss)
3005      ss = MATMUL(cell%hmat, ss)
3006      xba = ss(1)
3007      yba = ss(2)
3008      zba = ss(3)
3009      ! cb
3010      ss = MATMUL(cell%h_inv, rr(:, 3) - rr(:, 2))
3011      ss = ss - NINT(ss)
3012      ss = MATMUL(cell%hmat, ss)
3013      xcb = ss(1)
3014      ycb = ss(2)
3015      zcb = ss(3)
3016      ! dc
3017      ss = MATMUL(cell%h_inv, rr(:, 4) - rr(:, 3))
3018      ss = ss - NINT(ss)
3019      ss = MATMUL(cell%hmat, ss)
3020      xdc = ss(1)
3021      ydc = ss(2)
3022      zdc = ss(3)
3023      !
3024      xt = yba*zcb - ycb*zba
3025      yt = zba*xcb - zcb*xba
3026      zt = xba*ycb - xcb*yba
3027      xu = ycb*zdc - ydc*zcb
3028      yu = zcb*xdc - zdc*xcb
3029      zu = xcb*ydc - xdc*ycb
3030      xtu = yt*zu - yu*zt
3031      ytu = zt*xu - zu*xt
3032      ztu = xt*yu - xu*yt
3033      rt2 = xt*xt + yt*yt + zt*zt
3034      ru2 = xu*xu + yu*yu + zu*zu
3035      rtru = SQRT(rt2*ru2)
3036      IF (rtru .NE. 0.0_dp) THEN
3037         rcb = SQRT(xcb*xcb + ycb*ycb + zcb*zcb)
3038         cosine = (xt*xu + yt*yu + zt*zu)/rtru
3039         sine = (xcb*xtu + ycb*ytu + zcb*ztu)/(rcb*rtru)
3040         cosine = MIN(1.0_dp, MAX(-1.0_dp, cosine))
3041         angle = ACOS(cosine)
3042         IF (sine .LT. 0.0_dp) angle = -angle
3043         !
3044         dt = angle ! [rad]
3045         dt = MOD(2.0E4_dp*pi + dt - o0, 2.0_dp*pi)
3046         IF (dt .GT. pi) dt = dt - 2.0_dp*pi
3047         dt = o0 + dt
3048         colvar%torsion_param%o0 = dt
3049         !
3050         !     calculate improper energy and master chain rule term
3051         !
3052         e = dt
3053         dedphi = 1.0_dp
3054         !
3055         !     chain rule terms for first derivative components
3056         !
3057         ! ca
3058         ss = MATMUL(cell%h_inv, rr(:, 3) - rr(:, 1))
3059         ss = ss - NINT(ss)
3060         ss = MATMUL(cell%hmat, ss)
3061         xca = ss(1)
3062         yca = ss(2)
3063         zca = ss(3)
3064         ! db
3065         ss = MATMUL(cell%h_inv, rr(:, 4) - rr(:, 2))
3066         ss = ss - NINT(ss)
3067         ss = MATMUL(cell%hmat, ss)
3068         xdb = ss(1)
3069         ydb = ss(2)
3070         zdb = ss(3)
3071         !
3072         dedxt = dedphi*(yt*zcb - ycb*zt)/(rt2*rcb)
3073         dedyt = dedphi*(zt*xcb - zcb*xt)/(rt2*rcb)
3074         dedzt = dedphi*(xt*ycb - xcb*yt)/(rt2*rcb)
3075         dedxu = -dedphi*(yu*zcb - ycb*zu)/(ru2*rcb)
3076         dedyu = -dedphi*(zu*xcb - zcb*xu)/(ru2*rcb)
3077         dedzu = -dedphi*(xu*ycb - xcb*yu)/(ru2*rcb)
3078         !
3079         !     compute first derivative components for this angle
3080         !
3081         dedxia = zcb*dedyt - ycb*dedzt
3082         dedyia = xcb*dedzt - zcb*dedxt
3083         dedzia = ycb*dedxt - xcb*dedyt
3084         dedzia = ycb*dedxt - xcb*dedyt
3085         dedxib = yca*dedzt - zca*dedyt + zdc*dedyu - ydc*dedzu
3086         dedyib = zca*dedxt - xca*dedzt + xdc*dedzu - zdc*dedxu
3087         dedzib = xca*dedyt - yca*dedxt + ydc*dedxu - xdc*dedyu
3088         dedxic = zba*dedyt - yba*dedzt + ydb*dedzu - zdb*dedyu
3089         dedyic = xba*dedzt - zba*dedxt + zdb*dedxu - xdb*dedzu
3090         dedzic = yba*dedxt - xba*dedyt + xdb*dedyu - ydb*dedxu
3091         dedxid = zcb*dedyu - ycb*dedzu
3092         dedyid = xcb*dedzu - zcb*dedxu
3093         dedzid = ycb*dedxu - xcb*dedyu
3094      ENDIF
3095      !
3096      colvar%ss = e
3097      IF (no_riemann_sheet) colvar%ss = ATAN2(SIN(e), COS(e))
3098      ftmp(1) = dedxia
3099      ftmp(2) = dedyia
3100      ftmp(3) = dedzia
3101      CALL put_derivative(colvar, 1, ftmp)
3102      ftmp(1) = dedxib
3103      ftmp(2) = dedyib
3104      ftmp(3) = dedzib
3105      CALL put_derivative(colvar, 2, ftmp)
3106      ftmp(1) = dedxic
3107      ftmp(2) = dedyic
3108      ftmp(3) = dedzic
3109      CALL put_derivative(colvar, 3, ftmp)
3110      ftmp(1) = dedxid
3111      ftmp(2) = dedyid
3112      ftmp(3) = dedzid
3113      CALL put_derivative(colvar, 4, ftmp)
3114   END SUBROUTINE torsion_colvar
3115
3116! **************************************************************************************************
3117!> \brief evaluates the force due (and on) the Q PARM collective variable
3118!> \param colvar ...
3119!> \param cell ...
3120!> \param subsys ...
3121!> \param particles ...
3122! **************************************************************************************************
3123   SUBROUTINE qparm_colvar(colvar, cell, subsys, particles)
3124      TYPE(colvar_type), POINTER                         :: colvar
3125      TYPE(cell_type), POINTER                           :: cell
3126      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
3127      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
3128         POINTER                                         :: particles
3129
3130      CHARACTER(len=*), PARAMETER :: routineN = 'qparm_colvar', routineP = moduleN//':'//routineN
3131
3132      INTEGER                                            :: aa, bb, cc, i, idim, ii, j, jj, l, mm, &
3133                                                            n_atoms_from, n_atoms_to, ncells(3)
3134      LOGICAL                                            :: include_images
3135      REAL(KIND=dp) :: denominator_tolerance, fact, ftmp(3), im_qlm, inv_n_atoms_from, nbond, &
3136         pre_fac, ql, qparm, r1cut, rcut, re_qlm, rij, rij_shift, shift(3), ss(3), ss0(3), xij(3), &
3137         xij_shift(3)
3138      REAL(KIND=dp), DIMENSION(3)                        :: d_im_qlm_dxi, d_nbond_dxi, d_ql_dxi, &
3139                                                            d_re_qlm_dxi, xpi, xpj
3140      TYPE(particle_list_type), POINTER                  :: particles_i
3141      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
3142
3143      ! settings for numerical derivatives
3144      !REAL(KIND=dp) :: ri_step, dx_bond_j, dy_bond_j, dz_bond_j
3145      !INTEGER :: idel
3146
3147      n_atoms_to = colvar%qparm_param%n_atoms_to
3148      n_atoms_from = colvar%qparm_param%n_atoms_from
3149      rcut = colvar%qparm_param%rcut
3150      l = colvar%qparm_param%l
3151      r1cut = colvar%qparm_param%rstart
3152      include_images = colvar%qparm_param%include_images
3153      NULLIFY (particles_i)
3154      CPASSERT(colvar%type_id == qparm_colvar_id)
3155      IF (PRESENT(particles)) THEN
3156         my_particles => particles
3157      ELSE
3158         CPASSERT(PRESENT(subsys))
3159         CALL cp_subsys_get(subsys, particles=particles_i)
3160         my_particles => particles_i%els
3161      END IF
3162      CPASSERT(r1cut .LT. rcut)
3163      denominator_tolerance = 1.0E-8_dp
3164
3165      !ri_step=0.1
3166      !DO idel=-50, 50
3167      !ftmp(:) = 0.0_dp
3168
3169      qparm = 0.0_dp
3170      inv_n_atoms_from = 1.0_dp/REAL(n_atoms_from, KIND=dp)
3171      DO ii = 1, n_atoms_from
3172         i = colvar%qparm_param%i_at_from(ii)
3173         CALL get_coordinates(colvar, i, xpi, my_particles)
3174         !xpi(1)=xpi(1)+idel*ri_step
3175         ql = 0.0_dp
3176         d_ql_dxi(:) = 0.0_dp
3177
3178         DO mm = -l, l
3179            nbond = 0.0_dp
3180            re_qlm = 0.0_dp
3181            im_qlm = 0.0_dp
3182            d_re_qlm_dxi(:) = 0.0_dp
3183            d_im_qlm_dxi(:) = 0.0_dp
3184            d_nbond_dxi(:) = 0.0_dp
3185
3186            jloop: DO jj = 1, n_atoms_to
3187
3188               j = colvar%qparm_param%i_at_to(jj)
3189               CALL get_coordinates(colvar, j, xpj, my_particles)
3190
3191               IF (include_images) THEN
3192
3193                  CPASSERT(cell%orthorhombic)
3194
3195                  ! determine how many cells must be included in each direction
3196                  ! based on rcut
3197                  xij(:) = xpj(:) - xpi(:)
3198                  ss = MATMUL(cell%h_inv, xij)
3199                  ! these are fractional coordinates of the closest periodic image
3200                  ! lie in the [-0.5,0.5] interval
3201                  ss0 = ss - NINT(ss)
3202                  DO idim = 1, 3
3203                     shift(:) = 0.0_dp
3204                     shift(idim) = 1.0_dp
3205                     xij_shift = MATMUL(cell%hmat, shift)
3206                     rij_shift = SQRT(DOT_PRODUCT(xij_shift, xij_shift))
3207                     ncells(idim) = FLOOR(rcut/rij_shift - 0.5)
3208                  ENDDO !idim
3209
3210                  !IF (mm.eq.0) WRITE(*,'(A8,3I3,A3,I10)') "Ncells:", ncells, "J:", j
3211                  shift(1:3) = 0.0_dp
3212                  DO aa = -ncells(1), ncells(1)
3213                     DO bb = -ncells(2), ncells(2)
3214                        DO cc = -ncells(3), ncells(3)
3215                           ! do not include the central atom
3216                           IF (i == j .AND. aa .EQ. 0 .AND. bb .EQ. 0 .AND. cc .EQ. 0) CYCLE
3217                           shift(1) = REAL(aa, KIND=dp)
3218                           shift(2) = REAL(bb, KIND=dp)
3219                           shift(3) = REAL(cc, KIND=dp)
3220                           xij = MATMUL(cell%hmat, ss0(:) + shift(:))
3221                           rij = SQRT(DOT_PRODUCT(xij, xij))
3222                           !IF (rij > rcut) THEN
3223                           !   IF (mm.EQ.0) WRITE(*,'(A8,4F10.5)') " --", shift, rij
3224                           !ELSE
3225                           !   IF (mm.EQ.0) WRITE(*,'(A8,4F10.5)') " ++", shift, rij
3226                           !ENDIF
3227                           IF (rij > rcut) CYCLE
3228
3229                           ! update qlm
3230                           CALL accumulate_qlm_over_neigbors(xij, rij, rcut, r1cut, &
3231                                                             denominator_tolerance, l, mm, nbond, re_qlm, im_qlm, &
3232                                                             d_re_qlm_dxi, d_im_qlm_dxi, d_nbond_dxi)
3233
3234                        ENDDO
3235                     ENDDO
3236                  ENDDO
3237
3238               ELSE
3239
3240                  IF (i == j) CYCLE jloop
3241                  xij(:) = xpj(:) - xpi(:)
3242                  rij = SQRT(DOT_PRODUCT(xij, xij))
3243                  IF (rij > rcut) CYCLE
3244
3245                  ! update qlm
3246                  CALL accumulate_qlm_over_neigbors(xij, rij, rcut, r1cut, &
3247                                                    denominator_tolerance, l, mm, nbond, re_qlm, im_qlm, &
3248                                                    d_re_qlm_dxi, d_im_qlm_dxi, d_nbond_dxi)
3249
3250               ENDIF ! include images
3251
3252            ENDDO jloop
3253
3254            ! this factor is necessary if one whishes to sum over m=0,L
3255            ! instead of m=-L,+L. This is off now because it is cheap and safe
3256            fact = 1.0_dp
3257            !IF (ABS(mm) .GT. 0) THEN
3258            !   fact = 2.0_dp
3259            !ELSE
3260            !   fact = 1.0_dp
3261            !ENDIF
3262
3263            IF (nbond .LT. denominator_tolerance) THEN
3264               CPWARN("QPARM: number of neighbors is very close to zero!")
3265            END IF
3266
3267            d_nbond_dxi(:) = d_nbond_dxi(:)/nbond
3268            re_qlm = re_qlm/nbond
3269            d_re_qlm_dxi(:) = d_re_qlm_dxi(:)/nbond - d_nbond_dxi(:)*re_qlm
3270            im_qlm = im_qlm/nbond
3271            d_im_qlm_dxi(:) = d_im_qlm_dxi(:)/nbond - d_nbond_dxi(:)*im_qlm
3272
3273            ql = ql + fact*(re_qlm*re_qlm + im_qlm*im_qlm)
3274            d_ql_dxi(:) = d_ql_dxi(:) &
3275                          + fact*2.0_dp*(re_qlm*d_re_qlm_dxi(:) + im_qlm*d_im_qlm_dxi(:))
3276
3277         ENDDO ! loop over m
3278
3279         pre_fac = (4.0_dp*pi)/(2.0_dp*l + 1)
3280         !WRITE(*,'(A8,2F10.5)') "  si = ", SQRT(pre_fac*ql)
3281         qparm = qparm + SQRT(pre_fac*ql)
3282         ftmp(:) = 0.5_dp*SQRT(pre_fac/ql)*d_ql_dxi(:)
3283         ! multiply by -1 because aparently we have to save the force, not the gradient
3284         ftmp(:) = -1.0_dp*ftmp(:)
3285
3286         CALL put_derivative(colvar, ii, ftmp)
3287
3288      ENDDO ! loop over i
3289
3290      colvar%ss = qparm*inv_n_atoms_from
3291      colvar%dsdr(:, :) = colvar%dsdr(:, :)*inv_n_atoms_from
3292
3293      !WRITE(*,'(A15,3E20.10)') "COLVAR+DER = ", ri_step*idel, colvar%ss, -ftmp(1)
3294
3295      !ENDDO ! numercal derivative
3296
3297   END SUBROUTINE qparm_colvar
3298
3299! **************************************************************************************************
3300!> \brief ...
3301!> \param xij ...
3302!> \param rij ...
3303!> \param rcut ...
3304!> \param r1cut ...
3305!> \param denominator_tolerance ...
3306!> \param ll ...
3307!> \param mm ...
3308!> \param nbond ...
3309!> \param re_qlm ...
3310!> \param im_qlm ...
3311!> \param d_re_qlm_dxi ...
3312!> \param d_im_qlm_dxi ...
3313!> \param d_nbond_dxi ...
3314! **************************************************************************************************
3315   SUBROUTINE accumulate_qlm_over_neigbors(xij, rij, rcut, r1cut, &
3316                                           denominator_tolerance, ll, mm, nbond, re_qlm, im_qlm, &
3317                                           d_re_qlm_dxi, d_im_qlm_dxi, d_nbond_dxi)
3318
3319      REAL(KIND=dp), INTENT(IN)                          :: xij(3), rij, rcut, r1cut, &
3320                                                            denominator_tolerance
3321      INTEGER, INTENT(IN)                                :: ll, mm
3322      REAL(KIND=dp), INTENT(INOUT)                       :: nbond, re_qlm, im_qlm, d_re_qlm_dxi(3), &
3323                                                            d_im_qlm_dxi(3), d_nbond_dxi(3)
3324
3325      REAL(KIND=dp)                                      :: bond, costheta, dplm, dylm, exp0, &
3326                                                            exp_fac, fi, plm, pre_fac, sqrt_c1
3327      REAL(KIND=dp), DIMENSION(3)                        :: dcosTheta, dfi
3328
3329      !bond = 1.0_dp/(1.0_dp+EXP(alpha*(rij-rcut)))
3330      ! RZK: infinitely differentiable smooth cutoff function
3331      ! that is precisely 1.0 below r1cut and precisely 0.0 above rcut
3332      IF (rij .GT. rcut) THEN
3333         !bond = 0.0_dp
3334         !exp_fac = 0.0_dp
3335         RETURN
3336      ELSE
3337         IF (rij .LT. r1cut) THEN
3338            bond = 1.0_dp
3339            exp_fac = 0.0_dp
3340         ELSE
3341            exp0 = EXP((r1cut - rcut)/(rij - rcut) - (r1cut - rcut)/(r1cut - rij))
3342            bond = 1.0_dp/(1.0_dp + exp0)
3343            exp_fac = ((rcut - r1cut)/(rij - rcut)**2 + (rcut - r1cut)/(r1cut - rij)**2)*exp0/(1.0_dp + exp0)**2
3344         ENDIF
3345      ENDIF
3346      IF (bond > 1.0_dp) THEN
3347         CPABORT("bond > 1.0_dp")
3348      END IF
3349      ! compute continuous bond order
3350      nbond = nbond + bond
3351      IF (ABS(xij(1)) .LT. denominator_tolerance &
3352          .AND. ABS(xij(2)) .LT. denominator_tolerance) THEN
3353         fi = 0.0_dp
3354      ELSE
3355         fi = ATAN2(xij(2), xij(1))
3356      ENDIF
3357
3358      costheta = xij(3)/rij
3359      IF (costheta > 1.0_dp) costheta = 1.0_dp
3360      IF (costheta < -1.0_dp) costheta = -1.0_dp
3361
3362      ! legendre works correctly only for positive m
3363      plm = legendre(costheta, ll, mm)
3364      dplm = dlegendre(costheta, ll, mm)
3365      IF ((ll + ABS(mm)) > maxfac) THEN
3366         CPABORT("(l+m) > maxfac")
3367      END IF
3368      ! use absolute m to compenstate for the defficiency of legendre
3369      sqrt_c1 = SQRT(((2*ll + 1)*fac(ll - ABS(mm)))/(4*pi*fac(ll + ABS(mm))))
3370      pre_fac = bond*sqrt_c1
3371      dylm = pre_fac*dplm
3372      !WHY? IF (plm < 0.0_dp) THEN
3373      !WHY?    dylm = -pre_fac*dplm
3374      !WHY? ELSE
3375      !WHY?    dylm = pre_fac*dplm
3376      !WHY? ENDIF
3377
3378      re_qlm = re_qlm + pre_fac*plm*COS(mm*fi)
3379      im_qlm = im_qlm + pre_fac*plm*SIN(mm*fi)
3380
3381      !WRITE(*,'(A8,2I4,F10.5)') "  Qlm = ", mm, j, bond
3382      !WRITE(*,'(A8,2I4,2F10.5)') "  Qlm = ", mm, j, re_qlm, im_qlm
3383
3384      dcosTheta(:) = xij(:)*xij(3)/(rij**3)
3385      dcosTheta(3) = dcosTheta(3) - 1.0_dp/rij
3386      ! use tangent half-angle formula to compute d_fi/d_xi
3387      ! http://math.stackexchange.com/questions/989877/continuous-differentiability-of-atan2
3388      ! +/- sign changed because xij = xj - xi
3389      dfi(1) = xij(2)/(xij(1)**2 + xij(2)**2)
3390      dfi(2) = -xij(1)/(xij(1)**2 + xij(2)**2)
3391      dfi(3) = 0.0_dp
3392      d_re_qlm_dxi(:) = d_re_qlm_dxi(:) &
3393                        + exp_fac*sqrt_c1*plm*COS(mm*fi)*xij(:)/rij &
3394                        + dylm*dcosTheta(:)*COS(mm*fi) &
3395                        + pre_fac*plm*mm*(-1.0_dp)*SIN(mm*fi)*dfi(:)
3396      d_im_qlm_dxi(:) = d_im_qlm_dxi(:) &
3397                        + exp_fac*sqrt_c1*plm*SIN(mm*fi)*xij(:)/rij &
3398                        + dylm*dcosTheta(:)*SIN(mm*fi) &
3399                        + pre_fac*plm*mm*(+1.0_dp)*COS(mm*fi)*dfi(:)
3400      d_nbond_dxi(:) = d_nbond_dxi(:) + exp_fac*xij(:)/rij
3401
3402   END SUBROUTINE accumulate_qlm_over_neigbors
3403
3404! **************************************************************************************************
3405!> \brief evaluates the force due (and on) the hydronium_shell collective variable
3406!> \param colvar ...
3407!> \param cell ...
3408!> \param subsys ...
3409!> \param particles ...
3410!> \author Marcel Baer
3411!> \note This function needs to be extended to the POINT structure!!
3412!>       non-standard conform.. it's a breach in the colvar module.
3413! **************************************************************************************************
3414   SUBROUTINE hydronium_shell_colvar(colvar, cell, subsys, particles)
3415      TYPE(colvar_type), POINTER                         :: colvar
3416      TYPE(cell_type), POINTER                           :: cell
3417      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
3418      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
3419         POINTER                                         :: particles
3420
3421      CHARACTER(len=*), PARAMETER :: routineN = 'hydronium_shell_colvar', &
3422         routineP = moduleN//':'//routineN
3423
3424      INTEGER                                            :: i, ii, j, jj, n_hydrogens, n_oxygens, &
3425                                                            pm, poh, poo, qm, qoh, qoo
3426      REAL(dp)                                           :: drji, fscalar, invden, lambda, nh, num, &
3427                                                            qtot, rji(3), roh, roo, rrel
3428      REAL(dp), ALLOCATABLE, DIMENSION(:)                :: M, noh, noo, qloc
3429      REAL(dp), ALLOCATABLE, DIMENSION(:, :, :)          :: dM, dnoh, dnoo
3430      REAL(dp), DIMENSION(3)                             :: rpi, rpj
3431      TYPE(particle_list_type), POINTER                  :: particles_i
3432      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
3433
3434      n_oxygens = colvar%hydronium_shell_param%n_oxygens
3435      n_hydrogens = colvar%hydronium_shell_param%n_hydrogens
3436      nh = colvar%hydronium_shell_param%nh
3437      poh = colvar%hydronium_shell_param%poh
3438      qoh = colvar%hydronium_shell_param%qoh
3439      poo = colvar%hydronium_shell_param%poo
3440      qoo = colvar%hydronium_shell_param%qoo
3441      roo = colvar%hydronium_shell_param%roo
3442      roh = colvar%hydronium_shell_param%roh
3443      lambda = colvar%hydronium_shell_param%lambda
3444      pm = colvar%hydronium_shell_param%pm
3445      qm = colvar%hydronium_shell_param%qm
3446
3447      NULLIFY (particles_i)
3448      CPASSERT(colvar%type_id == hydronium_shell_colvar_id)
3449      IF (PRESENT(particles)) THEN
3450         my_particles => particles
3451      ELSE
3452         CPASSERT(PRESENT(subsys))
3453         CALL cp_subsys_get(subsys, particles=particles_i)
3454         my_particles => particles_i%els
3455      END IF
3456
3457      ALLOCATE (dnoh(3, n_hydrogens, n_oxygens))
3458      ALLOCATE (noh(n_oxygens))
3459      ALLOCATE (M(n_oxygens))
3460      ALLOCATE (dM(3, n_hydrogens, n_oxygens))
3461
3462      ALLOCATE (dnoo(3, n_oxygens, n_oxygens))
3463      ALLOCATE (noo(n_oxygens))
3464
3465      ALLOCATE (qloc(n_oxygens))
3466
3467      ! Zero Arrays:
3468      dnoh = 0._dp
3469      dnoo = 0._dp
3470      M = 0._dp
3471      dM = 0._dp
3472      noo = 0._dp
3473      qloc = 0._dp
3474      noh = 0._dp
3475      DO ii = 1, n_oxygens
3476         i = colvar%hydronium_shell_param%i_oxygens(ii)
3477         rpi(:) = my_particles(i)%r(1:3)
3478         ! Computing M( n ( ii ) )
3479         DO jj = 1, n_hydrogens
3480            j = colvar%hydronium_shell_param%i_hydrogens(jj)
3481            rpj(:) = my_particles(j)%r(1:3)
3482            rji = pbc(rpj, rpi, cell)
3483            drji = SQRT(SUM(rji**2))
3484            rrel = drji/roh
3485            num = (1.0_dp - rrel**poh)
3486            invden = 1.0_dp/(1.0_dp - rrel**qoh)
3487            IF (ABS(1.0_dp - rrel) > 1.0E-6_dp) THEN
3488               noh(ii) = noh(ii) + num*invden
3489               fscalar = ((-poh*(rrel**(poh - 1))*invden) &
3490                          + num*(invden)**2*qoh*(rrel**(qoh - 1)))/(drji*roh)
3491               dnoh(1:3, jj, ii) = rji(1:3)*fscalar
3492            ELSE
3493               !correct limit if rji --> roh
3494               noh(ii) = noh(ii) + REAL(poh, dp)/REAL(qoh, dp)
3495               fscalar = REAL(poh*(poh - qoh), dp)/(REAL(2*qoh, dp)*roh*drji)
3496               dnoh(1:3, jj, ii) = rji(1:3)*fscalar
3497            ENDIF
3498         END DO
3499         M(ii) = 1.0_dp - (1.0_dp - (noh(ii)/nh)**pm)/ &
3500                 (1.0_dp - (noh(ii)/nh)**qm)
3501
3502         ! Computing no ( ii )
3503         DO jj = 1, n_oxygens
3504            IF (ii == jj) CYCLE
3505            j = colvar%hydronium_shell_param%i_oxygens(jj)
3506            rpj(:) = my_particles(j)%r(1:3)
3507            rji = pbc(rpj, rpi, cell)
3508            drji = SQRT(SUM(rji**2))
3509            rrel = drji/roo
3510            num = (1.0_dp - rrel**poo)
3511            invden = 1.0_dp/(1.0_dp - rrel**qoo)
3512            IF (ABS(1.0_dp - rrel) > 1.0E-6_dp) THEN
3513               noo(ii) = noo(ii) + num*invden
3514               fscalar = ((-poo*(rrel**(poo - 1))*invden) &
3515                          + num*(invden)**2*qoo*(rrel**(qoo - 1)))/(drji*roo)
3516               dnoo(1:3, jj, ii) = rji(1:3)*fscalar
3517            ELSE
3518               !correct limit if rji --> roo
3519               noo(ii) = noo(ii) + REAL(poo, dp)/REAL(qoo, dp)
3520               fscalar = REAL(poo*(poo - qoo), dp)/(REAL(2*qoo, dp)*roo*drji)
3521               dnoo(1:3, jj, ii) = rji(1:3)*fscalar
3522            ENDIF
3523         END DO
3524      END DO
3525
3526      ! computing qloc and Q
3527      qtot = 0._dp
3528      DO ii = 1, n_oxygens
3529         qloc(ii) = EXP(lambda*M(ii)*noo(ii))
3530         qtot = qtot + qloc(ii)
3531      END DO
3532      ! compute forces
3533      DO ii = 1, n_oxygens
3534         ! Computing f_OH
3535         DO jj = 1, n_hydrogens
3536            dM(1:3, jj, ii) = (pm*((noh(ii)/nh)**(pm - 1))*dnoh(1:3, jj, ii))/nh/ &
3537                              (1.0_dp - (noh(ii)/nh)**qm) - &
3538                              (1.0_dp - (noh(ii)/nh)**pm)/ &
3539                              ((1.0_dp - (noh(ii)/nh)**qm)**2)* &
3540                              qm*dnoh(1:3, jj, ii)*(noh(ii)/nh)**(qm - 1)/nh
3541
3542            colvar%dsdr(1:3, ii) = colvar%dsdr(1:3, ii) + qloc(ii)*dM(1:3, jj, ii)*noo(ii)/qtot
3543            colvar%dsdr(1:3, n_oxygens + jj) = colvar%dsdr(1:3, n_oxygens + jj) &
3544                                               - qloc(ii)*dM(1:3, jj, ii)*noo(ii)/qtot
3545         END DO
3546         ! Computing f_OO
3547         DO jj = 1, n_oxygens
3548            colvar%dsdr(1:3, ii) = colvar%dsdr(1:3, ii) + qloc(ii)*M(ii)*dnoo(1:3, jj, ii)/qtot
3549            colvar%dsdr(1:3, jj) = colvar%dsdr(1:3, jj) &
3550                                   - qloc(ii)*M(ii)*dnoo(1:3, jj, ii)/qtot
3551         END DO
3552      END DO
3553
3554      colvar%ss = LOG(qtot)/lambda
3555      DEALLOCATE (dnoh)
3556      DEALLOCATE (noh)
3557      DEALLOCATE (M)
3558      DEALLOCATE (dM)
3559      DEALLOCATE (dnoo)
3560      DEALLOCATE (noo)
3561      DEALLOCATE (qloc)
3562
3563   END SUBROUTINE hydronium_shell_colvar
3564
3565! **************************************************************************************************
3566!> \brief evaluates the force due (and on) the hydronium_dist collective variable;
3567!>        distance between hydronium and hydroxide ion
3568!> \param colvar ...
3569!> \param cell ...
3570!> \param subsys ...
3571!> \param particles ...
3572!> \author Dorothea Golze
3573! **************************************************************************************************
3574   SUBROUTINE hydronium_dist_colvar(colvar, cell, subsys, particles)
3575      TYPE(colvar_type), POINTER                         :: colvar
3576      TYPE(cell_type), POINTER                           :: cell
3577      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
3578      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
3579         POINTER                                         :: particles
3580
3581      CHARACTER(len=*), PARAMETER :: routineN = 'hydronium_dist_colvar', &
3582         routineP = moduleN//':'//routineN
3583
3584      INTEGER                                            :: i, ii, j, jj, k, kk, n_hydrogens, &
3585                                                            n_oxygens, offsetH, pf, pm, poh, qf, &
3586                                                            qm, qoh
3587      REAL(dp) :: drji, drki, fscalar, invden, lambda, nh, nn, num, rion, rion_den, rion_num, &
3588         rji(3), rki(3), roh, rrel, sum_expfac_F, sum_expfac_noh
3589      REAL(dp), ALLOCATABLE, DIMENSION(:)                :: dexpfac_F, dexpfac_noh, dF, dM, &
3590                                                            expfac_F, expfac_F_rki, expfac_noh, F, &
3591                                                            M, noh
3592      REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: dexpfac_F_rki
3593      REAL(dp), ALLOCATABLE, DIMENSION(:, :, :)          :: ddist_rki, dnoh
3594      REAL(dp), DIMENSION(3)                             :: rpi, rpj, rpk
3595      TYPE(particle_list_type), POINTER                  :: particles_i
3596      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
3597
3598      n_oxygens = colvar%hydronium_dist_param%n_oxygens
3599      n_hydrogens = colvar%hydronium_dist_param%n_hydrogens
3600      poh = colvar%hydronium_dist_param%poh
3601      qoh = colvar%hydronium_dist_param%qoh
3602      roh = colvar%hydronium_dist_param%roh
3603      pm = colvar%hydronium_dist_param%pm
3604      qm = colvar%hydronium_dist_param%qm
3605      nh = colvar%hydronium_dist_param%nh
3606      pf = colvar%hydronium_dist_param%pf
3607      qf = colvar%hydronium_dist_param%qf
3608      nn = colvar%hydronium_dist_param%nn
3609      lambda = colvar%hydronium_dist_param%lambda
3610
3611      NULLIFY (particles_i)
3612      CPASSERT(colvar%type_id == hydronium_dist_colvar_id)
3613      IF (PRESENT(particles)) THEN
3614         my_particles => particles
3615      ELSE
3616         CPASSERT(PRESENT(subsys))
3617         CALL cp_subsys_get(subsys, particles=particles_i)
3618         my_particles => particles_i%els
3619      END IF
3620
3621      ALLOCATE (dnoh(3, n_hydrogens, n_oxygens))
3622      ALLOCATE (noh(n_oxygens))
3623      ALLOCATE (M(n_oxygens), dM(n_oxygens))
3624      ALLOCATE (F(n_oxygens), dF(n_oxygens))
3625      ALLOCATE (expfac_noh(n_oxygens), dexpfac_noh(n_oxygens))
3626      ALLOCATE (expfac_F(n_oxygens), dexpfac_F(n_oxygens))
3627      ALLOCATE (ddist_rki(3, n_oxygens, n_oxygens))
3628      ALLOCATE (expfac_F_rki(n_oxygens))
3629      ALLOCATE (dexpfac_F_rki(n_oxygens, n_oxygens))
3630
3631      ! Zero Arrays:
3632      noh = 0._dp
3633      dnoh = 0._dp
3634      rion_num = 0._dp
3635      F = 0._dp
3636      M = 0._dp
3637      dF = 0._dp
3638      dM = 0._dp
3639      expfac_noh = 0._dp
3640      expfac_F = 0._dp
3641      sum_expfac_noh = 0._dp
3642      sum_expfac_F = 0._dp
3643      ddist_rki = 0._dp
3644      expfac_F_rki = 0._dp
3645      dexpfac_F_rki = 0._dp
3646
3647      !*** Calculate coordination function noh(ii) and its derivative
3648      DO ii = 1, n_oxygens
3649         i = colvar%hydronium_dist_param%i_oxygens(ii)
3650         rpi(:) = my_particles(i)%r(1:3)
3651         DO jj = 1, n_hydrogens
3652            j = colvar%hydronium_dist_param%i_hydrogens(jj)
3653            rpj(:) = my_particles(j)%r(1:3)
3654            rji = pbc(rpj, rpi, cell)
3655            drji = SQRT(SUM(rji**2))
3656            rrel = drji/roh
3657            num = (1.0_dp - rrel**poh)
3658            invden = 1.0_dp/(1.0_dp - rrel**qoh)
3659            IF (ABS(1.0_dp - rrel) > 1.0E-6_dp) THEN
3660               noh(ii) = noh(ii) + num*invden
3661               fscalar = ((-poh*(rrel**(poh - 1))*invden) &
3662                          + num*(invden)**2*qoh*(rrel**(qoh - 1)))/(drji*roh)
3663               dnoh(1:3, jj, ii) = rji(1:3)*fscalar
3664            ELSE
3665               !correct limit if rji --> roh
3666               noh(ii) = noh(ii) + REAL(poh, dp)/REAL(qoh, dp)
3667               fscalar = REAL(poh*(poh - qoh), dp)/(REAL(2*qoh, dp)*roh*drji)
3668               dnoh(1:3, jj, ii) = rji(1:3)*fscalar
3669            ENDIF
3670         END DO
3671      END DO
3672
3673      !*** Calculate M, dM, exp(lambda*M) and sum_[exp(lambda*M)]
3674      DO ii = 1, n_oxygens
3675         num = 1.0_dp - (noh(ii)/nh)**pm
3676         invden = 1.0_dp/(1.0_dp - (noh(ii)/nh)**qm)
3677         M(ii) = 1.0_dp - num*invden
3678         dM(ii) = (pm*(noh(ii)/nh)**(pm - 1)*invden - qm*num*(invden**2)* &
3679                   (noh(ii)/nh)**(qm - 1))/nh
3680         expfac_noh(ii) = EXP(lambda*noh(ii))
3681         dexpfac_noh(ii) = lambda*expfac_noh(ii)
3682         sum_expfac_noh = sum_expfac_noh + expfac_noh(ii)
3683      END DO
3684
3685      !*** Calculate F, dF, exp(lambda*F) and sum_[exp(lambda*F)]
3686      DO ii = 1, n_oxygens
3687         i = colvar%hydronium_dist_param%i_oxygens(ii)
3688         num = 1.0_dp - (noh(ii)/nn)**pf
3689         invden = 1.0_dp/(1.0_dp - (noh(ii)/nn)**qf)
3690         F(ii) = num*invden
3691         dF(ii) = (-pf*(noh(ii)/nn)**(pf - 1)*invden + qf*num*(invden**2)* &
3692                   (noh(ii)/nn)**(qf - 1))/nn
3693         expfac_F(ii) = EXP(lambda*F(ii))
3694         dexpfac_F(ii) = lambda*expfac_F(ii)
3695         sum_expfac_F = sum_expfac_F + expfac_F(ii)
3696      END DO
3697
3698      !*** Calculation numerator of rion
3699      DO ii = 1, n_oxygens
3700         i = colvar%hydronium_dist_param%i_oxygens(ii)
3701         rpi(:) = my_particles(i)%r(1:3)
3702         DO kk = 1, n_oxygens
3703            IF (ii == kk) CYCLE
3704            k = colvar%hydronium_dist_param%i_oxygens(kk)
3705            rpk(:) = my_particles(k)%r(1:3)
3706            rki = pbc(rpk, rpi, cell)
3707            drki = SQRT(SUM(rki**2))
3708            expfac_F_rki(ii) = expfac_F_rki(ii) + drki*expfac_F(kk)
3709            ddist_rki(1:3, kk, ii) = rki(1:3)/drki
3710            dexpfac_F_rki(kk, ii) = drki*dexpfac_F(kk)
3711         ENDDO
3712         rion_num = rion_num + M(ii)*expfac_noh(ii)*expfac_F_rki(ii)
3713      ENDDO
3714
3715      !*** Final H3O+/OH- distance
3716      rion_den = sum_expfac_noh*sum_expfac_F
3717      rion = rion_num/rion_den
3718      colvar%ss = rion
3719
3720      offsetH = n_oxygens
3721      !*** Derivatives numerator
3722      DO ii = 1, n_oxygens
3723         DO jj = 1, n_hydrogens
3724            colvar%dsdr(1:3, ii) = colvar%dsdr(1:3, ii) &
3725                                   + dM(ii)*dnoh(1:3, jj, ii)*expfac_noh(ii) &
3726                                   *expfac_F_rki(ii)/rion_den
3727            colvar%dsdr(1:3, offsetH + jj) = colvar%dsdr(1:3, offsetH + jj) &
3728                                             - dM(ii)*dnoh(1:3, jj, ii)*expfac_noh(ii) &
3729                                             *expfac_F_rki(ii)/rion_den
3730            colvar%dsdr(1:3, ii) = colvar%dsdr(1:3, ii) &
3731                                   + M(ii)*dexpfac_noh(ii)*dnoh(1:3, jj, ii) &
3732                                   *expfac_F_rki(ii)/rion_den
3733            colvar%dsdr(1:3, offsetH + jj) = colvar%dsdr(1:3, offsetH + jj) &
3734                                             - M(ii)*dexpfac_noh(ii)*dnoh(1:3, jj, ii) &
3735                                             *expfac_F_rki(ii)/rion_den
3736         ENDDO
3737         DO kk = 1, n_oxygens
3738            IF (ii == kk) CYCLE
3739            colvar%dsdr(1:3, kk) = colvar%dsdr(1:3, kk) &
3740                                   - M(ii)*expfac_noh(ii)*ddist_rki(1:3, kk, ii) &
3741                                   *expfac_F(kk)/rion_den
3742            colvar%dsdr(1:3, ii) = colvar%dsdr(1:3, ii) &
3743                                   + M(ii)*expfac_noh(ii)*ddist_rki(1:3, kk, ii) &
3744                                   *expfac_F(kk)/rion_den
3745            DO jj = 1, n_hydrogens
3746               colvar%dsdr(1:3, kk) = colvar%dsdr(1:3, kk) &
3747                                      + M(ii)*expfac_noh(ii)*dexpfac_F_rki(kk, ii) &
3748                                      *dF(kk)*dnoh(1:3, jj, kk)/rion_den
3749               colvar%dsdr(1:3, offsetH + jj) = colvar%dsdr(1:3, offsetH + jj) &
3750                                                - M(ii)*expfac_noh(ii)*dexpfac_F_rki(kk, ii) &
3751                                                *dF(kk)*dnoh(1:3, jj, kk)/rion_den
3752            ENDDO
3753         ENDDO
3754      ENDDO
3755      !*** Derivatives denominator
3756      DO ii = 1, n_oxygens
3757         DO jj = 1, n_hydrogens
3758            colvar%dsdr(1:3, ii) = colvar%dsdr(1:3, ii) &
3759                                   - rion_num*sum_expfac_F*dexpfac_noh(ii) &
3760                                   *dnoh(1:3, jj, ii)/(rion_den**2)
3761            colvar%dsdr(1:3, offsetH + jj) = colvar%dsdr(1:3, offsetH + jj) &
3762                                             + rion_num*sum_expfac_F*dexpfac_noh(ii) &
3763                                             *dnoh(1:3, jj, ii)/(rion_den**2)
3764            colvar%dsdr(1:3, ii) = colvar%dsdr(1:3, ii) &
3765                                   - rion_num*sum_expfac_noh*dexpfac_F(ii)*dF(ii) &
3766                                   *dnoh(1:3, jj, ii)/(rion_den**2)
3767            colvar%dsdr(1:3, offsetH + jj) = colvar%dsdr(1:3, offsetH + jj) &
3768                                             + rion_num*sum_expfac_noh*dexpfac_F(ii)*dF(ii) &
3769                                             *dnoh(1:3, jj, ii)/(rion_den**2)
3770         ENDDO
3771      ENDDO
3772
3773      DEALLOCATE (noh, M, F, expfac_noh, expfac_F)
3774      DEALLOCATE (dnoh, dM, dF, dexpfac_noh, dexpfac_F)
3775      DEALLOCATE (ddist_rki, expfac_F_rki, dexpfac_F_rki)
3776
3777   END SUBROUTINE hydronium_dist_colvar
3778
3779! **************************************************************************************************
3780!> \brief evaluates the force due (and on) the acid-hydronium-distance
3781!>        collective variable. Colvar: distance between carboxy group and
3782!>        hydronium ion.
3783!> \param colvar collective variable
3784!> \param cell ...
3785!> \param subsys ...
3786!> \param particles ...
3787!> \author Dorothea Golze
3788!> \note this function does not use POINTS, not reasonable for this colvar
3789! **************************************************************************************************
3790   SUBROUTINE acid_hyd_dist_colvar(colvar, cell, subsys, particles)
3791      TYPE(colvar_type), POINTER                         :: colvar
3792      TYPE(cell_type), POINTER                           :: cell
3793      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
3794      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
3795         POINTER                                         :: particles
3796
3797      CHARACTER(len=*), PARAMETER :: routineN = 'acid_hyd_dist_colvar', &
3798         routineP = moduleN//':'//routineN
3799
3800      INTEGER                                            :: i, ii, j, jj, k, kk, n_hydrogens, &
3801                                                            n_oxygens_acid, n_oxygens_water, &
3802                                                            offsetH, offsetO, paoh, pcut, pwoh, &
3803                                                            qaoh, qcut, qwoh
3804      REAL(dp), ALLOCATABLE, DIMENSION(:)                :: dexpfac, expfac, nwoh
3805      REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: dexpfac_rik
3806      REAL(dp), ALLOCATABLE, DIMENSION(:, :, :)          :: ddist_rik, dnaoh, dnwoh
3807      REAL(KIND=dp) :: dfcut, drik, drji, drjk, fbrace, fcut, fscalar, invden, invden_cut, lambda, &
3808         naoh, nc, num, num_cut, raoh, rik(3), rion, rion_den, rion_num, rji(3), rjk(3), rpi(3), &
3809         rpj(3), rpk(3), rrel, rwoh
3810      TYPE(particle_list_type), POINTER                  :: particles_i
3811      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
3812
3813      NULLIFY (my_particles, particles_i)
3814
3815      n_oxygens_water = colvar%acid_hyd_dist_param%n_oxygens_water
3816      n_oxygens_acid = colvar%acid_hyd_dist_param%n_oxygens_acid
3817      n_hydrogens = colvar%acid_hyd_dist_param%n_hydrogens
3818      pwoh = colvar%acid_hyd_dist_param%pwoh
3819      qwoh = colvar%acid_hyd_dist_param%qwoh
3820      paoh = colvar%acid_hyd_dist_param%paoh
3821      qaoh = colvar%acid_hyd_dist_param%qaoh
3822      pcut = colvar%acid_hyd_dist_param%pcut
3823      qcut = colvar%acid_hyd_dist_param%qcut
3824      rwoh = colvar%acid_hyd_dist_param%rwoh
3825      raoh = colvar%acid_hyd_dist_param%raoh
3826      nc = colvar%acid_hyd_dist_param%nc
3827      lambda = colvar%acid_hyd_dist_param%lambda
3828      ALLOCATE (expfac(n_oxygens_water))
3829      ALLOCATE (nwoh(n_oxygens_water))
3830      ALLOCATE (dnwoh(3, n_hydrogens, n_oxygens_water))
3831      ALLOCATE (dnaoh(3, n_hydrogens, n_oxygens_acid))
3832      ALLOCATE (dexpfac(n_oxygens_water))
3833      ALLOCATE (ddist_rik(3, n_oxygens_water, n_oxygens_acid))
3834      ALLOCATE (dexpfac_rik(n_oxygens_water, n_oxygens_acid))
3835      rion_den = 0._dp
3836      rion_num = 0._dp
3837      nwoh(:) = 0._dp
3838      naoh = 0._dp
3839      dnaoh(:, :, :) = 0._dp
3840      dnwoh(:, :, :) = 0._dp
3841      ddist_rik(:, :, :) = 0._dp
3842      dexpfac(:) = 0._dp
3843      dexpfac_rik(:, :) = 0._dp
3844
3845      CPASSERT(colvar%type_id == acid_hyd_dist_colvar_id)
3846      IF (PRESENT(particles)) THEN
3847         my_particles => particles
3848      ELSE
3849         CPASSERT(PRESENT(subsys))
3850         CALL cp_subsys_get(subsys, particles=particles_i)
3851         my_particles => particles_i%els
3852      END IF
3853
3854      ! Calculate coordination functions nwoh(ii) and denominator of rion
3855      DO ii = 1, n_oxygens_water
3856         i = colvar%acid_hyd_dist_param%i_oxygens_water(ii)
3857         rpi(:) = my_particles(i)%r(1:3)
3858         DO jj = 1, n_hydrogens
3859            j = colvar%acid_hyd_dist_param%i_hydrogens(jj)
3860            rpj(:) = my_particles(j)%r(1:3)
3861            rji = pbc(rpj, rpi, cell)
3862            drji = SQRT(SUM(rji**2))
3863            rrel = drji/rwoh
3864            num = 1.0_dp - rrel**pwoh
3865            invden = 1.0_dp/(1.0_dp - rrel**qwoh)
3866            IF (ABS(1.0_dp - rrel) > 1.0E-6_dp) THEN
3867               nwoh(ii) = nwoh(ii) + num*invden
3868               fscalar = (-pwoh*(rrel**(pwoh - 1))*invden &
3869                          + num*(invden**2)*qwoh*(rrel**(qwoh - 1)))/(drji*rwoh)
3870               dnwoh(1:3, jj, ii) = rji(1:3)*fscalar
3871            ELSE
3872               !correct limit if rji --> rwoh
3873               nwoh(ii) = nwoh(ii) + REAL(pwoh, dp)/REAL(qwoh, dp)
3874               fscalar = REAL(pwoh*(pwoh - qwoh), dp)/(REAL(2*qwoh, dp)*rwoh*drji)
3875               dnwoh(1:3, jj, ii) = rji(1:3)*fscalar
3876            ENDIF
3877         ENDDO
3878         expfac(ii) = EXP(lambda*nwoh(ii))
3879         dexpfac(ii) = lambda*expfac(ii)
3880         rion_den = rion_den + expfac(ii)
3881      ENDDO
3882
3883      ! Calculate nominator of rion
3884      DO kk = 1, n_oxygens_acid
3885         k = colvar%acid_hyd_dist_param%i_oxygens_acid(kk)
3886         rpk(:) = my_particles(k)%r(1:3)
3887         DO ii = 1, n_oxygens_water
3888            i = colvar%acid_hyd_dist_param%i_oxygens_water(ii)
3889            rpi(:) = my_particles(i)%r(1:3)
3890            rik = pbc(rpi, rpk, cell)
3891            drik = SQRT(SUM(rik**2))
3892            rion_num = rion_num + drik*expfac(ii)
3893            ddist_rik(1:3, ii, kk) = rik(1:3)/drik
3894            dexpfac_rik(ii, kk) = drik*dexpfac(ii)
3895         ENDDO
3896      ENDDO
3897
3898      !Calculate cutoff function
3899      DO kk = 1, n_oxygens_acid
3900         k = colvar%acid_hyd_dist_param%i_oxygens_acid(kk)
3901         rpk(:) = my_particles(k)%r(1:3)
3902         DO jj = 1, n_hydrogens
3903            j = colvar%acid_hyd_dist_param%i_hydrogens(jj)
3904            rpj(:) = my_particles(j)%r(1:3)
3905            rjk = pbc(rpj, rpk, cell)
3906            drjk = SQRT(SUM(rjk**2))
3907            rrel = drjk/raoh
3908            num = 1.0_dp - rrel**paoh
3909            invden = 1.0_dp/(1.0_dp - rrel**qaoh)
3910            IF (ABS(1.0_dp - rrel) > 1.0E-6_dp) THEN
3911               naoh = naoh + num*invden
3912               fscalar = (-paoh*(rrel**(paoh - 1))*invden &
3913                          + num*(invden**2)*qaoh*(rrel**(qaoh - 1)))/(drjk*raoh)
3914               dnaoh(1:3, jj, kk) = rjk(1:3)*fscalar
3915            ELSE
3916               !correct limit if rjk --> raoh
3917               naoh = naoh + REAL(paoh, dp)/REAL(qaoh, dp)
3918               fscalar = REAL(paoh*(paoh - qaoh), dp)/(REAL(2*qaoh, dp)*raoh*drjk)
3919               dnaoh(1:3, jj, kk) = rjk(1:3)*fscalar
3920            ENDIF
3921         ENDDO
3922      ENDDO
3923      num_cut = 1.0_dp - (naoh/nc)**pcut
3924      invden_cut = 1.0_dp/(1.0_dp - (naoh/nc)**qcut)
3925      fcut = num_cut*invden_cut
3926
3927      !Final distance acid - hydronium
3928      fbrace = rion_num/rion_den/2.0_dp
3929      rion = fcut*fbrace
3930      colvar%ss = rion
3931
3932      !Derivatives of fcut
3933      dfcut = ((-pcut*(naoh/nc)**(pcut - 1)*invden_cut) &
3934               + num_cut*(invden_cut**2)*qcut*(naoh/nc)**(qcut - 1))/nc
3935      offsetO = n_oxygens_water
3936      offsetH = n_oxygens_water + n_oxygens_acid
3937      DO kk = 1, n_oxygens_acid
3938         DO jj = 1, n_hydrogens
3939            colvar%dsdr(1:3, offsetO + kk) = colvar%dsdr(1:3, offsetO + kk) &
3940                                             + dfcut*dnaoh(1:3, jj, kk)*fbrace
3941            colvar%dsdr(1:3, offsetH + jj) = colvar%dsdr(1:3, offsetH + jj) &
3942                                             - dfcut*dnaoh(1:3, jj, kk)*fbrace
3943         ENDDO
3944      ENDDO
3945
3946      !Derivatives of fbrace
3947      !***nominator
3948      DO kk = 1, n_oxygens_acid
3949         DO ii = 1, n_oxygens_water
3950            colvar%dsdr(1:3, offsetO + kk) = colvar%dsdr(1:3, offsetO + kk) &
3951                                             + fcut*ddist_rik(1:3, ii, kk)*expfac(ii)/rion_den/2.0_dp
3952            colvar%dsdr(1:3, ii) = colvar%dsdr(1:3, ii) &
3953                                   - fcut*ddist_rik(1:3, ii, kk)*expfac(ii)/rion_den/2.0_dp
3954            DO jj = 1, n_hydrogens
3955               colvar%dsdr(1:3, ii) = colvar%dsdr(1:3, ii) &
3956                                      + fcut*dexpfac_rik(ii, kk)*dnwoh(1:3, jj, ii)/rion_den/2.0_dp
3957               colvar%dsdr(1:3, offsetH + jj) = colvar%dsdr(1:3, offsetH + jj) &
3958                                                - fcut*dexpfac_rik(ii, kk)*dnwoh(1:3, jj, ii)/rion_den/2.0_dp
3959            ENDDO
3960         ENDDO
3961      ENDDO
3962      !***denominator
3963      DO ii = 1, n_oxygens_water
3964         DO jj = 1, n_hydrogens
3965            colvar%dsdr(1:3, ii) = colvar%dsdr(1:3, ii) &
3966                                   - fcut*rion_num*dexpfac(ii)*dnwoh(1:3, jj, ii)/2.0_dp/(rion_den**2)
3967            colvar%dsdr(1:3, offsetH + jj) = colvar%dsdr(1:3, offsetH + jj) &
3968                                             + fcut*rion_num*dexpfac(ii)*dnwoh(1:3, jj, ii)/2.0_dp/(rion_den**2)
3969         ENDDO
3970      ENDDO
3971
3972   END SUBROUTINE acid_hyd_dist_colvar
3973
3974! **************************************************************************************************
3975!> \brief evaluates the force due (and on) the acid-hydronium-shell
3976!>        collective variable. Colvar: number of oxygens in 1st shell of the
3977!>        hydronium.
3978!> \param colvar collective variable
3979!> \param cell ...
3980!> \param subsys ...
3981!> \param particles ...
3982!> \author Dorothea Golze
3983!> \note this function does not use POINTS, not reasonable for this colvar
3984! **************************************************************************************************
3985   SUBROUTINE acid_hyd_shell_colvar(colvar, cell, subsys, particles)
3986      TYPE(colvar_type), POINTER                         :: colvar
3987      TYPE(cell_type), POINTER                           :: cell
3988      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
3989      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
3990         POINTER                                         :: particles
3991
3992      CHARACTER(len=*), PARAMETER :: routineN = 'acid_hyd_shell_colvar', &
3993         routineP = moduleN//':'//routineN
3994
3995      INTEGER :: i, ii, j, jj, k, kk, n_hydrogens, n_oxygens_acid, n_oxygens_water, offsetH, &
3996         offsetO, paoh, pcut, pm, poo, pwoh, qaoh, qcut, qm, qoo, qwoh, tt
3997      REAL(dp), ALLOCATABLE, DIMENSION(:)                :: dM, M, noo, nwoh, qloc
3998      REAL(dp), ALLOCATABLE, DIMENSION(:, :, :)          :: dnaoh, dnoo, dnwoh
3999      REAL(KIND=dp) :: dfcut, drji, drjk, drki, fcut, fscalar, invden, invden_cut, lambda, naoh, &
4000         nc, nh, num, num_cut, qsol, qtot, raoh, rji(3), rjk(3), rki(3), roo, rpi(3), rpj(3), &
4001         rpk(3), rrel, rwoh
4002      TYPE(particle_list_type), POINTER                  :: particles_i
4003      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
4004
4005      NULLIFY (my_particles, particles_i)
4006
4007      n_oxygens_water = colvar%acid_hyd_shell_param%n_oxygens_water
4008      n_oxygens_acid = colvar%acid_hyd_shell_param%n_oxygens_acid
4009      n_hydrogens = colvar%acid_hyd_shell_param%n_hydrogens
4010      pwoh = colvar%acid_hyd_shell_param%pwoh
4011      qwoh = colvar%acid_hyd_shell_param%qwoh
4012      paoh = colvar%acid_hyd_shell_param%paoh
4013      qaoh = colvar%acid_hyd_shell_param%qaoh
4014      poo = colvar%acid_hyd_shell_param%poo
4015      qoo = colvar%acid_hyd_shell_param%qoo
4016      pm = colvar%acid_hyd_shell_param%pm
4017      qm = colvar%acid_hyd_shell_param%qm
4018      pcut = colvar%acid_hyd_shell_param%pcut
4019      qcut = colvar%acid_hyd_shell_param%qcut
4020      rwoh = colvar%acid_hyd_shell_param%rwoh
4021      raoh = colvar%acid_hyd_shell_param%raoh
4022      roo = colvar%acid_hyd_shell_param%roo
4023      nc = colvar%acid_hyd_shell_param%nc
4024      nh = colvar%acid_hyd_shell_param%nh
4025      lambda = colvar%acid_hyd_shell_param%lambda
4026      ALLOCATE (nwoh(n_oxygens_water))
4027      ALLOCATE (dnwoh(3, n_hydrogens, n_oxygens_water))
4028      ALLOCATE (dnaoh(3, n_hydrogens, n_oxygens_acid))
4029      ALLOCATE (M(n_oxygens_water))
4030      ALLOCATE (dM(n_oxygens_water))
4031      ALLOCATE (noo(n_oxygens_water))
4032      ALLOCATE (dnoo(3, n_oxygens_water + n_oxygens_acid, n_oxygens_water))
4033      ALLOCATE (qloc(n_oxygens_water))
4034      nwoh(:) = 0._dp
4035      naoh = 0._dp
4036      noo = 0._dp
4037      dnaoh(:, :, :) = 0._dp
4038      dnwoh(:, :, :) = 0._dp
4039      dnoo(:, :, :) = 0._dp
4040      M = 0._dp
4041      dM = 0._dp
4042      qtot = 0._dp
4043
4044      CPASSERT(colvar%type_id == acid_hyd_shell_colvar_id)
4045      IF (PRESENT(particles)) THEN
4046         my_particles => particles
4047      ELSE
4048         CPASSERT(PRESENT(subsys))
4049         CALL cp_subsys_get(subsys, particles=particles_i)
4050         my_particles => particles_i%els
4051      END IF
4052
4053      ! Calculate coordination functions nwoh(ii) and the M function
4054      DO ii = 1, n_oxygens_water
4055         i = colvar%acid_hyd_shell_param%i_oxygens_water(ii)
4056         rpi(:) = my_particles(i)%r(1:3)
4057         DO jj = 1, n_hydrogens
4058            j = colvar%acid_hyd_shell_param%i_hydrogens(jj)
4059            rpj(:) = my_particles(j)%r(1:3)
4060            rji = pbc(rpj, rpi, cell)
4061            drji = SQRT(SUM(rji**2))
4062            rrel = drji/rwoh
4063            num = 1.0_dp - rrel**pwoh
4064            invden = 1.0_dp/(1.0_dp - rrel**qwoh)
4065            IF (ABS(1.0_dp - rrel) > 1.0E-6_dp) THEN
4066               nwoh(ii) = nwoh(ii) + num*invden
4067               fscalar = (-pwoh*(rrel**(pwoh - 1))*invden &
4068                          + num*(invden**2)*qwoh*(rrel**(qwoh - 1)))/(drji*rwoh)
4069               dnwoh(1:3, jj, ii) = rji(1:3)*fscalar
4070            ELSE
4071               !correct limit if rji --> rwoh
4072               nwoh(ii) = nwoh(ii) + REAL(pwoh, dp)/REAL(qwoh, dp)
4073               fscalar = REAL(pwoh*(pwoh - qwoh), dp)/(REAL(2*qwoh, dp)*rwoh*drji)
4074               dnwoh(1:3, jj, ii) = rji(1:3)*fscalar
4075            ENDIF
4076         ENDDO
4077      ENDDO
4078
4079      ! calculate M function
4080      DO ii = 1, n_oxygens_water
4081         num = 1.0_dp - (nwoh(ii)/nh)**pm
4082         invden = 1.0_dp/(1.0_dp - (nwoh(ii)/nh)**qm)
4083         M(ii) = 1.0_dp - num*invden
4084         dM(ii) = (pm*(nwoh(ii)/nh)**(pm - 1)*invden - qm*num*(invden**2)* &
4085                   (nwoh(ii)/nh)**(qm - 1))/nh
4086      ENDDO
4087
4088      ! Computing noo(i)
4089      DO ii = 1, n_oxygens_water
4090         i = colvar%acid_hyd_shell_param%i_oxygens_water(ii)
4091         rpi(:) = my_particles(i)%r(1:3)
4092         DO kk = 1, n_oxygens_water + n_oxygens_acid
4093            IF (ii == kk) CYCLE
4094            IF (kk <= n_oxygens_water) THEN
4095               k = colvar%acid_hyd_shell_param%i_oxygens_water(kk)
4096               rpk(:) = my_particles(k)%r(1:3)
4097            ELSE
4098               tt = kk - n_oxygens_water
4099               k = colvar%acid_hyd_shell_param%i_oxygens_acid(tt)
4100               rpk(:) = my_particles(k)%r(1:3)
4101            ENDIF
4102            rki = pbc(rpk, rpi, cell)
4103            drki = SQRT(SUM(rki**2))
4104            rrel = drki/roo
4105            num = 1.0_dp - rrel**poo
4106            invden = 1.0_dp/(1.0_dp - rrel**qoo)
4107            IF (ABS(1.0_dp - rrel) > 1.0E-6_dp) THEN
4108               noo(ii) = noo(ii) + num*invden
4109               fscalar = (-poo*(rrel**(poo - 1))*invden &
4110                          + num*(invden**2)*qoo*(rrel**(qoo - 1)))/(drki*roo)
4111               dnoo(1:3, kk, ii) = rki(1:3)*fscalar
4112            ELSE
4113               !correct limit if rki --> roo
4114               noo(ii) = noo(ii) + REAL(poo, dp)/REAL(qoo, dp)
4115               fscalar = REAL(poo*(poo - qoo), dp)/(REAL(2*qoo, dp)*roo*drki)
4116               dnoo(1:3, kk, ii) = rki(1:3)*fscalar
4117            ENDIF
4118         ENDDO
4119      ENDDO
4120
4121      !Calculate cutoff function
4122      DO kk = 1, n_oxygens_acid
4123         k = colvar%acid_hyd_shell_param%i_oxygens_acid(kk)
4124         rpk(:) = my_particles(k)%r(1:3)
4125         DO jj = 1, n_hydrogens
4126            j = colvar%acid_hyd_shell_param%i_hydrogens(jj)
4127            rpj(:) = my_particles(j)%r(1:3)
4128            rjk = pbc(rpj, rpk, cell)
4129            drjk = SQRT(SUM(rjk**2))
4130            rrel = drjk/raoh
4131            num = 1.0_dp - rrel**paoh
4132            invden = 1.0_dp/(1.0_dp - rrel**qaoh)
4133            IF (ABS(1.0_dp - rrel) > 1.0E-6_dp) THEN
4134               naoh = naoh + num*invden
4135               fscalar = (-paoh*(rrel**(paoh - 1))*invden &
4136                          + num*(invden**2)*qaoh*(rrel**(qaoh - 1)))/(drjk*raoh)
4137               dnaoh(1:3, jj, kk) = rjk(1:3)*fscalar
4138            ELSE
4139               !correct limit if rjk --> raoh
4140               naoh = naoh + REAL(paoh, dp)/REAL(qaoh, dp)
4141               fscalar = REAL(paoh*(paoh - qaoh), dp)/(REAL(2*qaoh, dp)*raoh*drjk)
4142               dnaoh(1:3, jj, kk) = rjk(1:3)*fscalar
4143            ENDIF
4144         ENDDO
4145      ENDDO
4146      num_cut = 1.0_dp - (naoh/nc)**pcut
4147      invden_cut = 1.0_dp/(1.0_dp - (naoh/nc)**qcut)
4148      fcut = num_cut*invden_cut
4149
4150      ! Final value: number of oxygens in 1st shell of hydronium
4151      DO ii = 1, n_oxygens_water
4152         qloc(ii) = EXP(lambda*M(ii)*noo(ii))
4153         qtot = qtot + qloc(ii)
4154      ENDDO
4155      qsol = LOG(qtot)/lambda
4156      colvar%ss = fcut*qsol
4157
4158      ! Derivatives of fcut
4159      dfcut = ((-pcut*(naoh/nc)**(pcut - 1)*invden_cut) &
4160               + num_cut*(invden_cut**2)*qcut*(naoh/nc)**(qcut - 1))/nc
4161      offsetO = n_oxygens_water
4162      offsetH = n_oxygens_water + n_oxygens_acid
4163      DO kk = 1, n_oxygens_acid
4164         DO jj = 1, n_hydrogens
4165            colvar%dsdr(1:3, offsetO + kk) = colvar%dsdr(1:3, offsetO + kk) &
4166                                             + dfcut*dnaoh(1:3, jj, kk)*qsol
4167            colvar%dsdr(1:3, offsetH + jj) = colvar%dsdr(1:3, offsetH + jj) &
4168                                             - dfcut*dnaoh(1:3, jj, kk)*qsol
4169         ENDDO
4170      ENDDO
4171
4172      ! Derivatives of qsol
4173      !*** M derivatives
4174      DO ii = 1, n_oxygens_water
4175         fscalar = fcut*qloc(ii)*dM(ii)*noo(ii)/qtot
4176         DO jj = 1, n_hydrogens
4177            colvar%dsdr(1:3, ii) = colvar%dsdr(1:3, ii) &
4178                                   + fscalar*dnwoh(1:3, jj, ii)
4179            colvar%dsdr(1:3, offsetH + jj) = colvar%dsdr(1:3, offsetH + jj) &
4180                                             - fscalar*dnwoh(1:3, jj, ii)
4181         ENDDO
4182      ENDDO
4183      !*** noo derivatives
4184      DO ii = 1, n_oxygens_water
4185         fscalar = fcut*qloc(ii)*M(ii)/qtot
4186         DO kk = 1, n_oxygens_water + n_oxygens_acid
4187            IF (ii == kk) CYCLE
4188            colvar%dsdr(1:3, ii) = colvar%dsdr(1:3, ii) + fscalar*dnoo(1:3, kk, ii)
4189            colvar%dsdr(1:3, kk) = colvar%dsdr(1:3, kk) - fscalar*dnoo(1:3, kk, ii)
4190         ENDDO
4191      ENDDO
4192
4193   END SUBROUTINE acid_hyd_shell_colvar
4194
4195! **************************************************************************************************
4196!> \brief evaluates the force due (and on) the coordination-chain collective variable
4197!> \param colvar ...
4198!> \param cell ...
4199!> \param subsys ...
4200!> \param particles ...
4201!> \author MI
4202!> \note When the third set of atoms is not defined, this variable is equivalent
4203!>       to the simple coordination number.
4204! **************************************************************************************************
4205   SUBROUTINE coord_colvar(colvar, cell, subsys, particles)
4206      TYPE(colvar_type), POINTER                         :: colvar
4207      TYPE(cell_type), POINTER                           :: cell
4208      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
4209      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
4210         POINTER                                         :: particles
4211
4212      CHARACTER(len=*), PARAMETER :: routineN = 'coord_colvar', routineP = moduleN//':'//routineN
4213
4214      INTEGER                                            :: i, ii, j, jj, k, kk, n_atoms_from, &
4215                                                            n_atoms_to_a, n_atoms_to_b, p_a, p_b, &
4216                                                            q_a, q_b
4217      REAL(dp) :: dfunc_ij, dfunc_jk, func_ij, func_jk, func_k, inv_n_atoms_from, invden_ij, &
4218         invden_jk, ncoord, num_ij, num_jk, r_0_a, r_0_b, rdist_ij, rdist_jk, rij, rjk
4219      REAL(dp), DIMENSION(3)                             :: ftmp_i, ftmp_j, ftmp_k, ss, xij, xjk, &
4220                                                            xpi, xpj, xpk
4221      TYPE(particle_list_type), POINTER                  :: particles_i
4222      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
4223
4224! If we defined the coordination number with KINDS then we have still
4225! to fill few missing informations...
4226
4227      NULLIFY (particles_i)
4228      CPASSERT(colvar%type_id == coord_colvar_id)
4229      IF (PRESENT(particles)) THEN
4230         my_particles => particles
4231      ELSE
4232         CPASSERT(PRESENT(subsys))
4233         CALL cp_subsys_get(subsys, particles=particles_i)
4234         my_particles => particles_i%els
4235      END IF
4236      n_atoms_to_a = colvar%coord_param%n_atoms_to
4237      n_atoms_to_b = colvar%coord_param%n_atoms_to_b
4238      n_atoms_from = colvar%coord_param%n_atoms_from
4239      p_a = colvar%coord_param%nncrd
4240      q_a = colvar%coord_param%ndcrd
4241      r_0_a = colvar%coord_param%r_0
4242      p_b = colvar%coord_param%nncrd_b
4243      q_b = colvar%coord_param%ndcrd_b
4244      r_0_b = colvar%coord_param%r_0_b
4245
4246      ncoord = 0.0_dp
4247      inv_n_atoms_from = 1.0_dp/REAL(n_atoms_from, KIND=dp)
4248      DO ii = 1, n_atoms_from
4249         i = colvar%coord_param%i_at_from(ii)
4250         CALL get_coordinates(colvar, i, xpi, my_particles)
4251         DO jj = 1, n_atoms_to_a
4252            j = colvar%coord_param%i_at_to(jj)
4253            CALL get_coordinates(colvar, j, xpj, my_particles)
4254            ! define coordination of atom A with itself to be 0. also fixes rij==0 for the force calculation
4255            IF (i .EQ. j) CYCLE
4256            ss = MATMUL(cell%h_inv, xpi(:) - xpj(:))
4257            ss = ss - NINT(ss)
4258            xij = MATMUL(cell%hmat, ss)
4259            rij = SQRT(xij(1)**2 + xij(2)**2 + xij(3)**2)
4260            IF (rij < 1.0e-8_dp) CYCLE
4261            rdist_ij = rij/r_0_a
4262            IF (ABS(1.0_dp - rdist_ij) > EPSILON(0.0_dp)*1.0E+4_dp) THEN
4263               num_ij = (1.0_dp - rdist_ij**p_a)
4264               invden_ij = 1.0_dp/(1.0_dp - rdist_ij**q_a)
4265               func_ij = num_ij*invden_ij
4266               IF (rij < 1.0E-8_dp) THEN
4267                  ! provide the correct limit of the derivative
4268                  dfunc_ij = 0.0_dp
4269               ELSE
4270                  dfunc_ij = (-p_a*rdist_ij**(p_a - 1)*invden_ij &
4271                              + num_ij*(invden_ij)**2*q_a*rdist_ij**(q_a - 1))/(rij*r_0_a)
4272               END IF
4273            ELSE
4274               ! Provide the correct limit for function value and derivative
4275               func_ij = REAL(p_a, KIND=dp)/REAL(q_a, KIND=dp)
4276               dfunc_ij = REAL(p_a, KIND=dp)*REAL((-q_a + p_a), KIND=dp)/(REAL(2*q_a, KIND=dp)*r_0_a)
4277            END IF
4278            IF (n_atoms_to_b /= 0) THEN
4279               func_k = 0.0_dp
4280               DO kk = 1, n_atoms_to_b
4281                  k = colvar%coord_param%i_at_to_b(kk)
4282                  IF (k .EQ. j) CYCLE
4283                  CALL get_coordinates(colvar, k, xpk, my_particles)
4284                  ss = MATMUL(cell%h_inv, xpj(:) - xpk(:))
4285                  ss = ss - NINT(ss)
4286                  xjk = MATMUL(cell%hmat, ss)
4287                  rjk = SQRT(xjk(1)**2 + xjk(2)**2 + xjk(3)**2)
4288                  IF (rjk < 1.0e-8_dp) CYCLE
4289                  rdist_jk = rjk/r_0_b
4290                  IF (ABS(1.0_dp - rdist_jk) > EPSILON(0.0_dp)*1.0E+4_dp) THEN
4291                     num_jk = (1.0_dp - rdist_jk**p_b)
4292                     invden_jk = 1.0_dp/(1.0_dp - rdist_jk**q_b)
4293                     func_jk = num_jk*invden_jk
4294                     IF (rjk < 1.0E-8_dp) THEN
4295                        ! provide the correct limit of the derivative
4296                        dfunc_jk = 0.0_dp
4297                     ELSE
4298                        dfunc_jk = (-p_b*rdist_jk**(p_b - 1)*invden_jk &
4299                                    + num_jk*(invden_jk)**2*q_b*rdist_jk**(q_b - 1))/(rjk*r_0_b)
4300                     END IF
4301                  ELSE
4302                     ! Provide the correct limit for function value and derivative
4303                     func_jk = REAL(p_b, KIND=dp)/REAL(q_b, KIND=dp)
4304                     dfunc_jk = REAL(p_b, KIND=dp)*REAL((-q_b + p_b), KIND=dp)/(REAL(2*q_b, KIND=dp)*r_0_b)
4305                  ENDIF
4306                  func_k = func_k + func_jk
4307                  ftmp_k = -func_ij*dfunc_jk*xjk
4308                  CALL put_derivative(colvar, n_atoms_from + n_atoms_to_a + kk, ftmp_k)
4309
4310                  ftmp_j = -dfunc_ij*xij*func_jk + func_ij*dfunc_jk*xjk
4311                  CALL put_derivative(colvar, n_atoms_from + jj, ftmp_j)
4312               END DO
4313            ELSE
4314               func_k = 1.0_dp
4315               dfunc_jk = 0.0_dp
4316               ftmp_j = -dfunc_ij*xij
4317               CALL put_derivative(colvar, n_atoms_from + jj, ftmp_j)
4318            END IF
4319            ncoord = ncoord + func_ij*func_k
4320            ftmp_i = dfunc_ij*xij*func_k
4321            CALL put_derivative(colvar, ii, ftmp_i)
4322         ENDDO
4323      ENDDO
4324      colvar%ss = ncoord*inv_n_atoms_from
4325      colvar%dsdr(:, :) = colvar%dsdr(:, :)*inv_n_atoms_from
4326   END SUBROUTINE coord_colvar
4327
4328! **************************************************************************************************
4329!> \brief ...
4330!> \param colvar ...
4331!> \param cell ...
4332!> \param subsys ...
4333!> \param particles ...
4334! **************************************************************************************************
4335   SUBROUTINE mindist_colvar(colvar, cell, subsys, particles)
4336
4337      TYPE(colvar_type), POINTER                         :: colvar
4338      TYPE(cell_type), POINTER                           :: cell
4339      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
4340      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
4341         POINTER                                         :: particles
4342
4343      CHARACTER(len=*), PARAMETER :: routineN = 'mindist_colvar', routineP = moduleN//':'//routineN
4344
4345      INTEGER                                            :: i, ii, j, jj, n_coord_from, n_coord_to, &
4346                                                            n_dist_from, p, q
4347      REAL(dp) :: den_n, den_Q, fscalar, ftemp_i(3), inv_den_n, inv_den_Q, lambda, num_n, num_Q, &
4348         Qfunc, r12, r_cut, rfact, rij(3), rpi(3), rpj(3)
4349      REAL(dp), DIMENSION(:), POINTER                    :: dqfunc_dnL, expnL, nLcoord, sum_rij
4350      REAL(dp), DIMENSION(:, :, :), POINTER              :: dnLcoord, dqfunc_dr
4351      TYPE(particle_list_type), POINTER                  :: particles_i
4352      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
4353
4354! If we defined the coordination number with KINDS then we have still
4355! to fill few missing informations...
4356
4357      NULLIFY (particles_i)
4358      CPASSERT(colvar%type_id == mindist_colvar_id)
4359      IF (PRESENT(particles)) THEN
4360         my_particles => particles
4361      ELSE
4362         CPASSERT(PRESENT(subsys))
4363         CALL cp_subsys_get(subsys, particles=particles_i)
4364         my_particles => particles_i%els
4365      END IF
4366
4367      n_dist_from = colvar%mindist_param%n_dist_from
4368      n_coord_from = colvar%mindist_param%n_coord_from
4369      n_coord_to = colvar%mindist_param%n_coord_to
4370      p = colvar%mindist_param%p_exp
4371      q = colvar%mindist_param%q_exp
4372      r_cut = colvar%mindist_param%r_cut
4373      lambda = colvar%mindist_param%lambda
4374
4375      NULLIFY (nLcoord, dnLcoord, dqfunc_dr, dqfunc_dnL, expnL, sum_rij)
4376      ALLOCATE (nLcoord(n_coord_from))
4377      ALLOCATE (dnLcoord(3, n_coord_from, n_coord_to))
4378      ALLOCATE (expnL(n_coord_from))
4379      ALLOCATE (sum_rij(n_coord_from))
4380      ALLOCATE (dqfunc_dr(3, n_dist_from, n_coord_from))
4381      ALLOCATE (dqfunc_dnL(n_coord_from))
4382
4383      ! coordination numbers
4384      nLcoord = 0.0_dp
4385      dnLcoord = 0.0_dp
4386      expnL = 0.0_dp
4387      den_Q = 0.0_dp
4388      DO i = 1, n_coord_from
4389         ii = colvar%mindist_param%i_coord_from(i)
4390         rpi = my_particles(ii)%r(1:3)
4391         DO j = 1, n_coord_to
4392            jj = colvar%mindist_param%i_coord_to(j)
4393            rpj = my_particles(jj)%r(1:3)
4394            rij = pbc(rpj, rpi, cell)
4395            r12 = SQRT(rij(1)*rij(1) + rij(2)*rij(2) + rij(3)*rij(3))
4396            rfact = r12/r_cut
4397            num_n = 1.0_dp - rfact**p
4398            den_n = 1.0_dp - rfact**q
4399            inv_den_n = 1.0_dp/den_n
4400            IF (ABS(inv_den_n) < 1.e-10_dp) THEN
4401               inv_den_n = 1.e-10_dp
4402               num_n = ABS(num_n)
4403            END IF
4404
4405            fscalar = (-p*rfact**(p - 1) + num_n*q*rfact**(q - 1)*inv_den_n)*inv_den_n/(r_cut*r12)
4406
4407            dnLcoord(1, i, j) = rij(1)*fscalar
4408            dnLcoord(2, i, j) = rij(2)*fscalar
4409            dnLcoord(3, i, j) = rij(3)*fscalar
4410
4411            nLcoord(i) = nLcoord(i) + num_n*inv_den_n
4412         END DO
4413         expnL(i) = EXP(lambda*nLcoord(i))
4414!dbg
4415! write(*,*) ii,nLcoord(i),expnL(i)
4416!dbg
4417         den_Q = den_Q + expnL(i)
4418      END DO
4419      inv_den_Q = 1.0_dp/den_Q
4420
4421      qfunc = 0.0_dp
4422      dqfunc_dr = 0.0_dp
4423      dqfunc_dnL = 0.0_dp
4424      num_Q = 0.0_dp
4425      sum_rij = 0.0_dp
4426      DO i = 1, n_dist_from
4427         ii = colvar%mindist_param%i_dist_from(i)
4428         rpi = my_particles(ii)%r(1:3)
4429         DO j = 1, n_coord_from
4430            jj = colvar%mindist_param%i_coord_from(j)
4431            rpj = my_particles(jj)%r(1:3)
4432            rij = pbc(rpj, rpi, cell)
4433            r12 = SQRT(rij(1)*rij(1) + rij(2)*rij(2) + rij(3)*rij(3))
4434
4435!dbg
4436! write(*,*) ii,jj,rpi(1:3),rpj(1:3),rij(1:3),r12
4437!dbg
4438            num_Q = num_Q + r12*expnL(j)
4439
4440            sum_rij(j) = sum_rij(j) + r12
4441            dqfunc_dr(1, i, j) = expnL(j)*rij(1)/r12
4442            dqfunc_dr(2, i, j) = expnL(j)*rij(2)/r12
4443            dqfunc_dr(3, i, j) = expnL(j)*rij(3)/r12
4444
4445         END DO
4446
4447      END DO
4448
4449      ! Function and derivatives
4450      qfunc = num_Q*inv_den_Q
4451      dqfunc_dr = dqfunc_dr*inv_den_Q
4452      colvar%ss = qfunc
4453!dbg
4454!      write(*,*) ' ss ',  colvar%ss
4455! stop
4456!dbg
4457
4458      DO i = 1, n_coord_from
4459         dqfunc_dnL(i) = lambda*expnL(i)*inv_den_Q*(sum_rij(i) - num_Q*inv_den_Q)
4460      END DO
4461
4462      !Compute Forces
4463      DO i = 1, n_dist_from
4464         DO j = 1, n_coord_from
4465            ftemp_i(1) = dqfunc_dr(1, i, j)
4466            ftemp_i(2) = dqfunc_dr(2, i, j)
4467            ftemp_i(3) = dqfunc_dr(3, i, j)
4468
4469            CALL put_derivative(colvar, i, ftemp_i)
4470            CALL put_derivative(colvar, j + n_dist_from, -ftemp_i)
4471
4472         END DO
4473      END DO
4474      DO i = 1, n_coord_from
4475         DO j = 1, n_coord_to
4476            ftemp_i(1) = dqfunc_dnL(i)*dnLcoord(1, i, j)
4477            ftemp_i(2) = dqfunc_dnL(i)*dnLcoord(2, i, j)
4478            ftemp_i(3) = dqfunc_dnL(i)*dnLcoord(3, i, j)
4479
4480            CALL put_derivative(colvar, i + n_dist_from, ftemp_i)
4481            CALL put_derivative(colvar, j + n_dist_from + n_coord_from, -ftemp_i)
4482
4483         END DO
4484      END DO
4485
4486      DEALLOCATE (nLcoord)
4487      DEALLOCATE (dnLcoord)
4488      DEALLOCATE (expnL)
4489      DEALLOCATE (dqfunc_dr)
4490      DEALLOCATE (sum_rij)
4491      DEALLOCATE (dqfunc_dnL)
4492
4493   END SUBROUTINE mindist_colvar
4494
4495! **************************************************************************************************
4496!> \brief  evaluates function and forces due to a combination of COLVARs
4497!> \param colvar ...
4498!> \param cell ...
4499!> \param subsys ...
4500!> \param particles ...
4501!> \author Teodoro Laino [tlaino] - 12.2008
4502! **************************************************************************************************
4503   SUBROUTINE combine_colvar(colvar, cell, subsys, particles)
4504      TYPE(colvar_type), POINTER                         :: colvar
4505      TYPE(cell_type), POINTER                           :: cell
4506      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
4507      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
4508         POINTER                                         :: particles
4509
4510      CHARACTER(len=*), PARAMETER :: routineN = 'combine_colvar', routineP = moduleN//':'//routineN
4511
4512      CHARACTER(LEN=default_string_length)               :: def_error, this_error
4513      CHARACTER(LEN=default_string_length), &
4514         ALLOCATABLE, DIMENSION(:)                       :: my_par
4515      INTEGER                                            :: i, ii, j, ncolv, ndim
4516      REAL(dp)                                           :: err
4517      REAL(dp), ALLOCATABLE, DIMENSION(:)                :: dss_vals, my_val, ss_vals
4518      REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: fi
4519      TYPE(particle_list_type), POINTER                  :: particles_i
4520      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
4521
4522      CPASSERT(colvar%type_id == combine_colvar_id)
4523      IF (PRESENT(particles)) THEN
4524         my_particles => particles
4525      ELSE
4526         CPASSERT(PRESENT(subsys))
4527         CALL cp_subsys_get(subsys, particles=particles_i)
4528         my_particles => particles_i%els
4529      END IF
4530
4531      ncolv = SIZE(colvar%combine_cvs_param%colvar_p)
4532      ALLOCATE (ss_vals(ncolv))
4533      ALLOCATE (dss_vals(ncolv))
4534
4535      ! Evaluate the individual COLVARs
4536      DO i = 1, ncolv
4537         CALL colvar_recursive_eval(colvar%combine_cvs_param%colvar_p(i)%colvar, cell, my_particles)
4538         ss_vals(i) = colvar%combine_cvs_param%colvar_p(i)%colvar%ss
4539      ENDDO
4540
4541      ! Evaluate the combination of the COLVARs
4542      CALL initf(1)
4543      ndim = SIZE(colvar%combine_cvs_param%c_parameters) + &
4544             SIZE(colvar%combine_cvs_param%variables)
4545      ALLOCATE (my_par(ndim))
4546      my_par(1:SIZE(colvar%combine_cvs_param%variables)) = colvar%combine_cvs_param%variables
4547      my_par(SIZE(colvar%combine_cvs_param%variables) + 1:) = colvar%combine_cvs_param%c_parameters
4548      ALLOCATE (my_val(ndim))
4549      my_val(1:SIZE(colvar%combine_cvs_param%variables)) = ss_vals
4550      my_val(SIZE(colvar%combine_cvs_param%variables) + 1:) = colvar%combine_cvs_param%v_parameters
4551      CALL parsef(1, TRIM(colvar%combine_cvs_param%function), my_par)
4552      colvar%ss = evalf(1, my_val)
4553      DO i = 1, ncolv
4554         dss_vals(i) = evalfd(1, i, my_val, colvar%combine_cvs_param%dx, err)
4555         IF ((ABS(err) > colvar%combine_cvs_param%lerr)) THEN
4556            WRITE (this_error, "(A,G12.6,A)") "(", err, ")"
4557            WRITE (def_error, "(A,G12.6,A)") "(", colvar%combine_cvs_param%lerr, ")"
4558            CALL compress(this_error, .TRUE.)
4559            CALL compress(def_error, .TRUE.)
4560            CALL cp_warn(__LOCATION__, &
4561                         'ASSERTION (cond) failed at line '//cp_to_string(__LINE__)// &
4562                         ' Error '//TRIM(this_error)//' in computing numerical derivatives larger then'// &
4563                         TRIM(def_error)//' . ')
4564         END IF
4565      END DO
4566      DEALLOCATE (my_val)
4567      DEALLOCATE (my_par)
4568      CALL finalizef()
4569
4570      ! Evaluate forces
4571      ALLOCATE (fi(3, colvar%n_atom_s))
4572      ii = 0
4573      DO i = 1, ncolv
4574         DO j = 1, colvar%combine_cvs_param%colvar_p(i)%colvar%n_atom_s
4575            ii = ii + 1
4576            fi(:, ii) = colvar%combine_cvs_param%colvar_p(i)%colvar%dsdr(:, j)*dss_vals(i)
4577         END DO
4578      END DO
4579
4580      DO i = 1, colvar%n_atom_s
4581         CALL put_derivative(colvar, i, fi(:, i))
4582      END DO
4583
4584      DEALLOCATE (fi)
4585      DEALLOCATE (ss_vals)
4586      DEALLOCATE (dss_vals)
4587   END SUBROUTINE combine_colvar
4588
4589! **************************************************************************************************
4590!> \brief evaluates the force due (and on) reaction path collective variable
4591!>             ss(R) = [\sum_i i*dt exp{-\lambda \sum_a(S_a(R)-f_a(i))^2}]/
4592!>                     [\sum_i exp{-\lambda \sum_a(S_a(R)-f_a(i))^2}]
4593!> \param colvar ...
4594!> \param cell ...
4595!> \param subsys ...
4596!> \param particles ...
4597!> \par History
4598!>      extended MI 01.2010
4599!> \author fschiff
4600!> \note the system is still able to move in the space spanned by the CV
4601!>       perpendicular to the path
4602! **************************************************************************************************
4603   SUBROUTINE reaction_path_colvar(colvar, cell, subsys, particles)
4604      TYPE(colvar_type), POINTER                         :: colvar
4605      TYPE(cell_type), POINTER                           :: cell
4606      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
4607      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
4608         POINTER                                         :: particles
4609
4610      CHARACTER(len=*), PARAMETER :: routineN = 'reaction_path_colvar', &
4611         routineP = moduleN//':'//routineN
4612
4613      TYPE(particle_list_type), POINTER                  :: particles_i
4614      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
4615
4616      CPASSERT(colvar%type_id == reaction_path_colvar_id)
4617      IF (PRESENT(particles)) THEN
4618         my_particles => particles
4619      ELSE
4620         CPASSERT(PRESENT(subsys))
4621         CALL cp_subsys_get(subsys, particles=particles_i)
4622         my_particles => particles_i%els
4623      END IF
4624
4625      IF (colvar%reaction_path_param%dist_rmsd) THEN
4626         CALL rpath_dist_rmsd(colvar, my_particles)
4627      ELSEIF (colvar%reaction_path_param%rmsd) THEN
4628         CALL rpath_rmsd(colvar, my_particles)
4629      ELSE
4630         CALL rpath_colvar(colvar, cell, my_particles)
4631      END IF
4632
4633   END SUBROUTINE reaction_path_colvar
4634
4635! **************************************************************************************************
4636!> \brief  position along the path calculated using selected colvars
4637!>         as compared to functions describing the variation of these same colvars
4638!>         along the path given as reference
4639!> \param colvar ...
4640!> \param cell ...
4641!> \param particles ...
4642!> \author fschiff
4643! **************************************************************************************************
4644   SUBROUTINE rpath_colvar(colvar, cell, particles)
4645      TYPE(colvar_type), POINTER                         :: colvar
4646      TYPE(cell_type), POINTER                           :: cell
4647      TYPE(particle_type), DIMENSION(:), POINTER         :: particles
4648
4649      CHARACTER(len=*), PARAMETER :: routineN = 'rpath_colvar', routineP = moduleN//':'//routineN
4650
4651      INTEGER                                            :: i, iend, ii, istart, j, k, ncolv, nconf
4652      REAL(dp)                                           :: lambda, step_size
4653      REAL(dp), ALLOCATABLE, DIMENSION(:)                :: s1, ss_vals
4654      REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: ds1, f_vals, fi, s1v
4655      REAL(dp), ALLOCATABLE, DIMENSION(:, :, :)          :: ds1v
4656
4657      istart = colvar%reaction_path_param%function_bounds(1)
4658      iend = colvar%reaction_path_param%function_bounds(2)
4659
4660      nconf = colvar%reaction_path_param%nr_frames
4661      step_size = colvar%reaction_path_param%step_size
4662      ncolv = colvar%reaction_path_param%n_components
4663      lambda = colvar%reaction_path_param%lambda
4664      ALLOCATE (f_vals(ncolv, istart:iend))
4665      f_vals(:, :) = colvar%reaction_path_param%f_vals
4666      ALLOCATE (ss_vals(ncolv))
4667
4668      DO i = 1, ncolv
4669         CALL colvar_recursive_eval(colvar%reaction_path_param%colvar_p(i)%colvar, cell, particles)
4670         ss_vals(i) = colvar%reaction_path_param%colvar_p(i)%colvar%ss
4671      ENDDO
4672
4673      ALLOCATE (s1v(2, istart:iend))
4674      ALLOCATE (ds1v(ncolv, 2, istart:iend))
4675
4676      ALLOCATE (s1(2))
4677      ALLOCATE (ds1(ncolv, 2))
4678
4679      DO k = istart, iend
4680         s1v(1, k) = REAL(k, kind=dp)*step_size*EXP(-lambda*DOT_PRODUCT(ss_vals(:) - f_vals(:, k), ss_vals(:) - f_vals(:, k)))
4681         s1v(2, k) = EXP(-lambda*DOT_PRODUCT(ss_vals(:) - f_vals(:, k), ss_vals(:) - f_vals(:, k)))
4682         DO j = 1, ncolv
4683            ds1v(j, 1, k) = f_vals(j, k)*s1v(1, k)
4684            ds1v(j, 2, k) = f_vals(j, k)*s1v(2, k)
4685         END DO
4686      END DO
4687      DO i = 1, 2
4688         s1(i) = accurate_sum(s1v(i, :))
4689         DO j = 1, ncolv
4690            ds1(j, i) = accurate_sum(ds1v(j, i, :))
4691         END DO
4692      END DO
4693
4694      colvar%ss = s1(1)/s1(2)/REAL(nconf - 1, dp)
4695
4696      ALLOCATE (fi(3, colvar%n_atom_s))
4697
4698      ii = 0
4699      DO i = 1, ncolv
4700         DO j = 1, colvar%reaction_path_param%colvar_p(i)%colvar%n_atom_s
4701            ii = ii + 1
4702            fi(:, ii) = colvar%reaction_path_param%colvar_p(i)%colvar%dsdr(:, j)*lambda* &
4703                        (ds1(i, 1)/s1(2)/REAL(nconf - 1, dp) - colvar%ss*ds1(i, 2)/s1(2))*2.0_dp
4704         END DO
4705      END DO
4706
4707      DO i = 1, colvar%n_atom_s
4708         CALL put_derivative(colvar, i, fi(:, i))
4709      END DO
4710
4711      DEALLOCATE (fi)
4712      DEALLOCATE (f_vals)
4713      DEALLOCATE (ss_vals)
4714      DEALLOCATE (s1v)
4715      DEALLOCATE (ds1v)
4716      DEALLOCATE (s1)
4717      DEALLOCATE (ds1)
4718
4719   END SUBROUTINE rpath_colvar
4720
4721! **************************************************************************************************
4722!> \brief  position along the path calculated from the positions of a selected list of
4723!>         atoms as compared to the same positions in reference
4724!>         configurations belonging to the given path.
4725!> \param colvar ...
4726!> \param particles ...
4727!> \date  01.2010
4728!> \author MI
4729! **************************************************************************************************
4730   SUBROUTINE rpath_dist_rmsd(colvar, particles)
4731      TYPE(colvar_type), POINTER                         :: colvar
4732      TYPE(particle_type), DIMENSION(:), POINTER         :: particles
4733
4734      CHARACTER(len=*), PARAMETER :: routineN = 'rpath_dist_rmsd', &
4735         routineP = moduleN//':'//routineN
4736
4737      INTEGER                                            :: i, iat, ii, ik, natom, nconf, rmsd_atom
4738      INTEGER, DIMENSION(:), POINTER                     :: iatom
4739      REAL(dp)                                           :: lambda, my_rmsd, s1(2), sum_exp
4740      REAL(dp), ALLOCATABLE, DIMENSION(:)                :: r, r0, vec_dif
4741      REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: dvec_dif, fi, riat, s1v
4742      REAL(dp), ALLOCATABLE, DIMENSION(:, :, :)          :: ds1
4743      REAL(dp), ALLOCATABLE, DIMENSION(:, :, :, :)       :: ds1v
4744      REAL(dp), DIMENSION(:, :), POINTER                 :: path_conf
4745
4746      nconf = colvar%reaction_path_param%nr_frames
4747      rmsd_atom = colvar%reaction_path_param%n_components
4748      lambda = colvar%reaction_path_param%lambda
4749      path_conf => colvar%reaction_path_param%r_ref
4750      iatom => colvar%reaction_path_param%i_rmsd
4751
4752      natom = SIZE(particles)
4753
4754      ALLOCATE (r0(3*natom))
4755      ALLOCATE (r(3*natom))
4756      ALLOCATE (riat(3, rmsd_atom))
4757      ALLOCATE (vec_dif(rmsd_atom))
4758      ALLOCATE (dvec_dif(3, rmsd_atom))
4759      ALLOCATE (s1v(2, nconf))
4760      ALLOCATE (ds1v(3, rmsd_atom, 2, nconf))
4761      ALLOCATE (ds1(3, rmsd_atom, 2))
4762      DO i = 1, natom
4763         ii = (i - 1)*3
4764         r0(ii + 1) = particles(i)%r(1)
4765         r0(ii + 2) = particles(i)%r(2)
4766         r0(ii + 3) = particles(i)%r(3)
4767      END DO
4768
4769      DO iat = 1, rmsd_atom
4770         ii = iatom(iat)
4771         riat(:, iat) = particles(ii)%r
4772      END DO
4773
4774      DO ik = 1, nconf
4775         DO i = 1, natom
4776            ii = (i - 1)*3
4777            r(ii + 1) = path_conf(ii + 1, ik)
4778            r(ii + 2) = path_conf(ii + 2, ik)
4779            r(ii + 3) = path_conf(ii + 3, ik)
4780         END DO
4781
4782         CALL rmsd3(particles, r, r0, output_unit=-1, my_val=my_rmsd, rotate=.TRUE.)
4783
4784         sum_exp = 0.0_dp
4785         DO iat = 1, rmsd_atom
4786            i = iatom(iat)
4787            ii = (i - 1)*3
4788            vec_dif(iat) = (riat(1, iat) - r(ii + 1))**2 + (riat(2, iat) - r(ii + 2))**2 &
4789                           + (riat(3, iat) - r(ii + 3))**2
4790            sum_exp = sum_exp + vec_dif(iat)
4791         END DO
4792
4793         s1v(1, ik) = REAL(ik - 1, dp)*EXP(-lambda*sum_exp)
4794         s1v(2, ik) = EXP(-lambda*sum_exp)
4795         DO iat = 1, rmsd_atom
4796            i = iatom(iat)
4797            ii = (i - 1)*3
4798            ds1v(1, iat, 1, ik) = r(ii + 1)*s1v(1, ik)
4799            ds1v(1, iat, 2, ik) = r(ii + 1)*s1v(2, ik)
4800            ds1v(2, iat, 1, ik) = r(ii + 2)*s1v(1, ik)
4801            ds1v(2, iat, 2, ik) = r(ii + 2)*s1v(2, ik)
4802            ds1v(3, iat, 1, ik) = r(ii + 3)*s1v(1, ik)
4803            ds1v(3, iat, 2, ik) = r(ii + 3)*s1v(2, ik)
4804         END DO
4805
4806      END DO
4807      s1(1) = accurate_sum(s1v(1, :))
4808      s1(2) = accurate_sum(s1v(2, :))
4809      DO i = 1, 2
4810         DO iat = 1, rmsd_atom
4811            ds1(1, iat, i) = accurate_sum(ds1v(1, iat, i, :))
4812            ds1(2, iat, i) = accurate_sum(ds1v(2, iat, i, :))
4813            ds1(3, iat, i) = accurate_sum(ds1v(3, iat, i, :))
4814         END DO
4815      END DO
4816
4817      colvar%ss = s1(1)/s1(2)/REAL(nconf - 1, dp)
4818
4819      ALLOCATE (fi(3, rmsd_atom))
4820
4821      DO iat = 1, rmsd_atom
4822         fi(1, iat) = 2.0_dp*lambda/s1(2)/REAL(nconf - 1, dp)*(ds1(1, iat, 1) - ds1(1, iat, 2)*s1(1)/s1(2))
4823         fi(2, iat) = 2.0_dp*lambda/s1(2)/REAL(nconf - 1, dp)*(ds1(2, iat, 1) - ds1(2, iat, 2)*s1(1)/s1(2))
4824         fi(3, iat) = 2.0_dp*lambda/s1(2)/REAL(nconf - 1, dp)*(ds1(3, iat, 1) - ds1(3, iat, 2)*s1(1)/s1(2))
4825         CALL put_derivative(colvar, iat, fi(:, iat))
4826      END DO
4827
4828      DEALLOCATE (fi)
4829      DEALLOCATE (r0)
4830      DEALLOCATE (r)
4831      DEALLOCATE (riat)
4832      DEALLOCATE (vec_dif)
4833      DEALLOCATE (dvec_dif)
4834      DEALLOCATE (s1v)
4835      DEALLOCATE (ds1v)
4836      DEALLOCATE (ds1)
4837
4838   END SUBROUTINE rpath_dist_rmsd
4839
4840! **************************************************************************************************
4841!> \brief ...
4842!> \param colvar ...
4843!> \param particles ...
4844! **************************************************************************************************
4845   SUBROUTINE rpath_rmsd(colvar, particles)
4846      TYPE(colvar_type), POINTER                         :: colvar
4847      TYPE(particle_type), DIMENSION(:), POINTER         :: particles
4848
4849      CHARACTER(len=*), PARAMETER :: routineN = 'rpath_rmsd', routineP = moduleN//':'//routineN
4850
4851      INTEGER                                            :: i, iat, ii, ik, natom, nconf, rmsd_atom
4852      INTEGER, DIMENSION(:), POINTER                     :: iatom
4853      REAL(dp)                                           :: lambda, my_rmsd, s1(2)
4854      REAL(dp), ALLOCATABLE, DIMENSION(:)                :: r, r0
4855      REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: fi, riat, s1v
4856      REAL(dp), ALLOCATABLE, DIMENSION(:, :, :)          :: ds1
4857      REAL(dp), ALLOCATABLE, DIMENSION(:, :, :, :)       :: ds1v
4858      REAL(dp), DIMENSION(:, :), POINTER                 :: path_conf
4859      REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: weight
4860      REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: drmsd
4861
4862      nconf = colvar%reaction_path_param%nr_frames
4863      rmsd_atom = colvar%reaction_path_param%n_components
4864      lambda = colvar%reaction_path_param%lambda
4865      path_conf => colvar%reaction_path_param%r_ref
4866      iatom => colvar%reaction_path_param%i_rmsd
4867
4868      natom = SIZE(particles)
4869
4870      ALLOCATE (r0(3*natom))
4871      ALLOCATE (r(3*natom))
4872      ALLOCATE (riat(3, rmsd_atom))
4873      ALLOCATE (s1v(2, nconf))
4874      ALLOCATE (ds1v(3, rmsd_atom, 2, nconf))
4875      ALLOCATE (ds1(3, rmsd_atom, 2))
4876      ALLOCATE (drmsd(3, natom))
4877      drmsd = 0.0_dp
4878      ALLOCATE (weight(natom))
4879
4880      DO i = 1, natom
4881         ii = (i - 1)*3
4882         r0(ii + 1) = particles(i)%r(1)
4883         r0(ii + 2) = particles(i)%r(2)
4884         r0(ii + 3) = particles(i)%r(3)
4885      END DO
4886
4887      DO iat = 1, rmsd_atom
4888         ii = iatom(iat)
4889         riat(:, iat) = particles(ii)%r
4890      END DO
4891
4892! set weights of atoms in the rmsd list
4893      weight = 0.0_dp
4894      DO iat = 1, rmsd_atom
4895         i = iatom(iat)
4896         weight(i) = 1.0_dp
4897      END DO
4898
4899      DO ik = 1, nconf
4900         DO i = 1, natom
4901            ii = (i - 1)*3
4902            r(ii + 1) = path_conf(ii + 1, ik)
4903            r(ii + 2) = path_conf(ii + 2, ik)
4904            r(ii + 3) = path_conf(ii + 3, ik)
4905         END DO
4906
4907         CALL rmsd3(particles, r0, r, output_unit=-1, weights=weight, my_val=my_rmsd, &
4908                    rotate=.FALSE., drmsd3=drmsd)
4909
4910         s1v(1, ik) = REAL(ik - 1, dp)*EXP(-lambda*my_rmsd)
4911         s1v(2, ik) = EXP(-lambda*my_rmsd)
4912         DO iat = 1, rmsd_atom
4913            i = iatom(iat)
4914            ds1v(1, iat, 1, ik) = drmsd(1, i)*s1v(1, ik)
4915            ds1v(1, iat, 2, ik) = drmsd(1, i)*s1v(2, ik)
4916            ds1v(2, iat, 1, ik) = drmsd(2, i)*s1v(1, ik)
4917            ds1v(2, iat, 2, ik) = drmsd(2, i)*s1v(2, ik)
4918            ds1v(3, iat, 1, ik) = drmsd(3, i)*s1v(1, ik)
4919            ds1v(3, iat, 2, ik) = drmsd(3, i)*s1v(2, ik)
4920         END DO
4921      END DO ! ik
4922
4923      s1(1) = accurate_sum(s1v(1, :))
4924      s1(2) = accurate_sum(s1v(2, :))
4925      DO i = 1, 2
4926         DO iat = 1, rmsd_atom
4927            ds1(1, iat, i) = accurate_sum(ds1v(1, iat, i, :))
4928            ds1(2, iat, i) = accurate_sum(ds1v(2, iat, i, :))
4929            ds1(3, iat, i) = accurate_sum(ds1v(3, iat, i, :))
4930         END DO
4931      END DO
4932
4933      colvar%ss = s1(1)/s1(2)/REAL(nconf - 1, dp)
4934
4935      ALLOCATE (fi(3, rmsd_atom))
4936
4937      DO iat = 1, rmsd_atom
4938         fi(1, iat) = -lambda/s1(2)/REAL(nconf - 1, dp)*(ds1(1, iat, 1) - ds1(1, iat, 2)*s1(1)/s1(2))
4939         fi(2, iat) = -lambda/s1(2)/REAL(nconf - 1, dp)*(ds1(2, iat, 1) - ds1(2, iat, 2)*s1(1)/s1(2))
4940         fi(3, iat) = -lambda/s1(2)/REAL(nconf - 1, dp)*(ds1(3, iat, 1) - ds1(3, iat, 2)*s1(1)/s1(2))
4941         CALL put_derivative(colvar, iat, fi(:, iat))
4942      END DO
4943
4944      DEALLOCATE (fi)
4945      DEALLOCATE (r0)
4946      DEALLOCATE (r)
4947      DEALLOCATE (riat)
4948      DEALLOCATE (s1v)
4949      DEALLOCATE (ds1v)
4950      DEALLOCATE (ds1)
4951      DEALLOCATE (drmsd)
4952      DEALLOCATE (weight)
4953
4954   END SUBROUTINE rpath_rmsd
4955
4956! **************************************************************************************************
4957!> \brief evaluates the force due (and on) distance from reaction path collective variable
4958!>             ss(R) = -1/\lambda \log[\sum_i exp{-\lambda \sum_a(S_a(R)-f_a(i))^2}]
4959!> \param colvar ...
4960!> \param cell ...
4961!> \param subsys ...
4962!> \param particles ...
4963!> \date 01.2010
4964!> \author MI
4965! **************************************************************************************************
4966   SUBROUTINE distance_from_path_colvar(colvar, cell, subsys, particles)
4967      TYPE(colvar_type), POINTER                         :: colvar
4968      TYPE(cell_type), POINTER                           :: cell
4969      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
4970      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
4971         POINTER                                         :: particles
4972
4973      CHARACTER(len=*), PARAMETER :: routineN = 'distance_from_path_colvar', &
4974         routineP = moduleN//':'//routineN
4975
4976      TYPE(particle_list_type), POINTER                  :: particles_i
4977      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
4978
4979      CPASSERT(colvar%type_id == distance_from_path_colvar_id)
4980      IF (PRESENT(particles)) THEN
4981         my_particles => particles
4982      ELSE
4983         CPASSERT(PRESENT(subsys))
4984         CALL cp_subsys_get(subsys, particles=particles_i)
4985         my_particles => particles_i%els
4986      END IF
4987
4988      IF (colvar%reaction_path_param%dist_rmsd) THEN
4989         CALL dpath_dist_rmsd(colvar, my_particles)
4990      ELSEIF (colvar%reaction_path_param%rmsd) THEN
4991         CALL dpath_rmsd(colvar, my_particles)
4992      ELSE
4993         CALL dpath_colvar(colvar, cell, my_particles)
4994      END IF
4995
4996   END SUBROUTINE distance_from_path_colvar
4997
4998! **************************************************************************************************
4999!> \brief  distance from path calculated using selected colvars
5000!>         as compared to functions describing the variation of these same colvars
5001!>         along the path given as reference
5002!> \param colvar ...
5003!> \param cell ...
5004!> \param particles ...
5005!> \date  01.2010
5006!> \author MI
5007! **************************************************************************************************
5008   SUBROUTINE dpath_colvar(colvar, cell, particles)
5009      TYPE(colvar_type), POINTER                         :: colvar
5010      TYPE(cell_type), POINTER                           :: cell
5011      TYPE(particle_type), DIMENSION(:), POINTER         :: particles
5012
5013      CHARACTER(len=*), PARAMETER :: routineN = 'dpath_colvar', routineP = moduleN//':'//routineN
5014
5015      INTEGER                                            :: i, iend, ii, istart, j, k, ncolv
5016      REAL(dp)                                           :: lambda, s1
5017      REAL(dp), ALLOCATABLE, DIMENSION(:)                :: ds1, s1v, ss_vals
5018      REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: ds1v, f_vals, fi
5019
5020      istart = colvar%reaction_path_param%function_bounds(1)
5021      iend = colvar%reaction_path_param%function_bounds(2)
5022
5023      ncolv = colvar%reaction_path_param%n_components
5024      lambda = colvar%reaction_path_param%lambda
5025      ALLOCATE (f_vals(ncolv, istart:iend))
5026      f_vals(:, :) = colvar%reaction_path_param%f_vals
5027      ALLOCATE (ss_vals(ncolv))
5028
5029      DO i = 1, ncolv
5030         CALL colvar_recursive_eval(colvar%reaction_path_param%colvar_p(i)%colvar, cell, particles)
5031         ss_vals(i) = colvar%reaction_path_param%colvar_p(i)%colvar%ss
5032      ENDDO
5033
5034      ALLOCATE (s1v(istart:iend))
5035      ALLOCATE (ds1v(ncolv, istart:iend))
5036      ALLOCATE (ds1(ncolv))
5037
5038      DO k = istart, iend
5039         s1v(k) = EXP(-lambda*DOT_PRODUCT(ss_vals(:) - f_vals(:, k), ss_vals(:) - f_vals(:, k)))
5040         DO j = 1, ncolv
5041            ds1v(j, k) = f_vals(j, k)*s1v(k)
5042         END DO
5043      END DO
5044
5045      s1 = accurate_sum(s1v(:))
5046      DO j = 1, ncolv
5047         ds1(j) = accurate_sum(ds1v(j, :))
5048      END DO
5049      colvar%ss = -1.0_dp/lambda*LOG(s1)
5050
5051      ALLOCATE (fi(3, colvar%n_atom_s))
5052
5053      ii = 0
5054      DO i = 1, ncolv
5055         DO j = 1, colvar%reaction_path_param%colvar_p(i)%colvar%n_atom_s
5056            ii = ii + 1
5057            fi(:, ii) = colvar%reaction_path_param%colvar_p(i)%colvar%dsdr(:, j)* &
5058                        2.0_dp*(ss_vals(i) - ds1(i)/s1)
5059         END DO
5060      END DO
5061
5062      DO i = 1, colvar%n_atom_s
5063         CALL put_derivative(colvar, i, fi(:, i))
5064      END DO
5065
5066      DEALLOCATE (fi)
5067      DEALLOCATE (f_vals)
5068      DEALLOCATE (ss_vals)
5069      DEALLOCATE (s1v)
5070      DEALLOCATE (ds1v)
5071      DEALLOCATE (ds1)
5072
5073   END SUBROUTINE dpath_colvar
5074
5075! **************************************************************************************************
5076!> \brief  distance from path calculated from the positions of a selected list of
5077!>         atoms as compared to the same positions in reference
5078!>         configurations belonging to the given path.
5079!> \param colvar ...
5080!> \param particles ...
5081!> \date  01.2010
5082!> \author MI
5083! **************************************************************************************************
5084   SUBROUTINE dpath_dist_rmsd(colvar, particles)
5085
5086      TYPE(colvar_type), POINTER                         :: colvar
5087      TYPE(particle_type), DIMENSION(:), POINTER         :: particles
5088
5089      CHARACTER(len=*), PARAMETER :: routineN = 'dpath_dist_rmsd', &
5090         routineP = moduleN//':'//routineN
5091
5092      INTEGER                                            :: i, iat, ii, ik, natom, nconf, rmsd_atom
5093      INTEGER, DIMENSION(:), POINTER                     :: iatom
5094      REAL(dp)                                           :: lambda, s1, sum_exp
5095      REAL(dp), ALLOCATABLE, DIMENSION(:)                :: r, r0, s1v, vec_dif
5096      REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: ds1, dvec_dif, fi, riat
5097      REAL(dp), ALLOCATABLE, DIMENSION(:, :, :)          :: ds1v
5098      REAL(dp), DIMENSION(:, :), POINTER                 :: path_conf
5099
5100      nconf = colvar%reaction_path_param%nr_frames
5101      rmsd_atom = colvar%reaction_path_param%n_components
5102      lambda = colvar%reaction_path_param%lambda
5103      path_conf => colvar%reaction_path_param%r_ref
5104      iatom => colvar%reaction_path_param%i_rmsd
5105
5106      natom = SIZE(particles)
5107
5108      ALLOCATE (r0(3*natom))
5109      ALLOCATE (r(3*natom))
5110      ALLOCATE (riat(3, rmsd_atom))
5111      ALLOCATE (vec_dif(rmsd_atom))
5112      ALLOCATE (dvec_dif(3, rmsd_atom))
5113      ALLOCATE (s1v(nconf))
5114      ALLOCATE (ds1v(3, rmsd_atom, nconf))
5115      ALLOCATE (ds1(3, rmsd_atom))
5116      DO i = 1, natom
5117         ii = (i - 1)*3
5118         r0(ii + 1) = particles(i)%r(1)
5119         r0(ii + 2) = particles(i)%r(2)
5120         r0(ii + 3) = particles(i)%r(3)
5121      END DO
5122
5123      DO iat = 1, rmsd_atom
5124         ii = iatom(iat)
5125         riat(:, iat) = particles(ii)%r
5126      END DO
5127
5128      DO ik = 1, nconf
5129         DO i = 1, natom
5130            ii = (i - 1)*3
5131            r(ii + 1) = path_conf(ii + 1, ik)
5132            r(ii + 2) = path_conf(ii + 2, ik)
5133            r(ii + 3) = path_conf(ii + 3, ik)
5134         END DO
5135
5136         CALL rmsd3(particles, r, r0, output_unit=-1, rotate=.TRUE.)
5137
5138         sum_exp = 0.0_dp
5139         DO iat = 1, rmsd_atom
5140            i = iatom(iat)
5141            ii = (i - 1)*3
5142            vec_dif(iat) = (riat(1, iat) - r(ii + 1))**2 + (riat(2, iat) - r(ii + 2))**2 + (riat(3, iat) - r(ii + 3))**2
5143            sum_exp = sum_exp + vec_dif(iat)
5144            dvec_dif(1, iat) = r(ii + 1)
5145            dvec_dif(2, iat) = r(ii + 2)
5146            dvec_dif(3, iat) = r(ii + 3)
5147         END DO
5148         s1v(ik) = EXP(-lambda*sum_exp)
5149         DO iat = 1, rmsd_atom
5150            ds1v(1, iat, ik) = dvec_dif(1, iat)*s1v(ik)
5151            ds1v(2, iat, ik) = dvec_dif(2, iat)*s1v(ik)
5152            ds1v(3, iat, ik) = dvec_dif(3, iat)*s1v(ik)
5153         END DO
5154      END DO
5155
5156      s1 = accurate_sum(s1v(:))
5157      DO iat = 1, rmsd_atom
5158         ds1(1, iat) = accurate_sum(ds1v(1, iat, :))
5159         ds1(2, iat) = accurate_sum(ds1v(2, iat, :))
5160         ds1(3, iat) = accurate_sum(ds1v(3, iat, :))
5161      END DO
5162      colvar%ss = -1.0_dp/lambda*LOG(s1)
5163
5164      ALLOCATE (fi(3, rmsd_atom))
5165
5166      DO iat = 1, rmsd_atom
5167         fi(:, iat) = 2.0_dp*(riat(:, iat) - ds1(:, iat)/s1)
5168         CALL put_derivative(colvar, iat, fi(:, iat))
5169      END DO
5170
5171      DEALLOCATE (fi)
5172      DEALLOCATE (r0)
5173      DEALLOCATE (r)
5174      DEALLOCATE (riat)
5175      DEALLOCATE (vec_dif)
5176      DEALLOCATE (dvec_dif)
5177      DEALLOCATE (s1v)
5178      DEALLOCATE (ds1v)
5179      DEALLOCATE (ds1)
5180   END SUBROUTINE dpath_dist_rmsd
5181
5182! **************************************************************************************************
5183!> \brief ...
5184!> \param colvar ...
5185!> \param particles ...
5186! **************************************************************************************************
5187   SUBROUTINE dpath_rmsd(colvar, particles)
5188
5189      TYPE(colvar_type), POINTER                         :: colvar
5190      TYPE(particle_type), DIMENSION(:), POINTER         :: particles
5191
5192      CHARACTER(len=*), PARAMETER :: routineN = 'dpath_rmsd', routineP = moduleN//':'//routineN
5193
5194      INTEGER                                            :: i, iat, ii, ik, natom, nconf, rmsd_atom
5195      INTEGER, DIMENSION(:), POINTER                     :: iatom
5196      REAL(dp)                                           :: lambda, my_rmsd, s1
5197      REAL(dp), ALLOCATABLE, DIMENSION(:)                :: r, r0, s1v
5198      REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: ds1, fi, riat
5199      REAL(dp), ALLOCATABLE, DIMENSION(:, :, :)          :: ds1v
5200      REAL(dp), DIMENSION(:, :), POINTER                 :: path_conf
5201      REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: weight
5202      REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: drmsd
5203
5204      nconf = colvar%reaction_path_param%nr_frames
5205      rmsd_atom = colvar%reaction_path_param%n_components
5206      lambda = colvar%reaction_path_param%lambda
5207      path_conf => colvar%reaction_path_param%r_ref
5208      iatom => colvar%reaction_path_param%i_rmsd
5209
5210      natom = SIZE(particles)
5211
5212      ALLOCATE (r0(3*natom))
5213      ALLOCATE (r(3*natom))
5214      ALLOCATE (riat(3, rmsd_atom))
5215      ALLOCATE (s1v(nconf))
5216      ALLOCATE (ds1v(3, rmsd_atom, nconf))
5217      ALLOCATE (ds1(3, rmsd_atom))
5218      ALLOCATE (drmsd(3, natom))
5219      drmsd = 0.0_dp
5220      ALLOCATE (weight(natom))
5221
5222      DO i = 1, natom
5223         ii = (i - 1)*3
5224         r0(ii + 1) = particles(i)%r(1)
5225         r0(ii + 2) = particles(i)%r(2)
5226         r0(ii + 3) = particles(i)%r(3)
5227      END DO
5228
5229      DO iat = 1, rmsd_atom
5230         ii = iatom(iat)
5231         riat(:, iat) = particles(ii)%r
5232      END DO
5233
5234! set weights of atoms in the rmsd list
5235      weight = 0.0_dp
5236      DO iat = 1, rmsd_atom
5237         i = iatom(iat)
5238         weight(i) = 1.0_dp
5239      END DO
5240
5241      DO ik = 1, nconf
5242         DO i = 1, natom
5243            ii = (i - 1)*3
5244            r(ii + 1) = path_conf(ii + 1, ik)
5245            r(ii + 2) = path_conf(ii + 2, ik)
5246            r(ii + 3) = path_conf(ii + 3, ik)
5247         END DO
5248
5249         CALL rmsd3(particles, r0, r, output_unit=-1, weights=weight, my_val=my_rmsd, &
5250                    rotate=.FALSE., drmsd3=drmsd)
5251
5252         s1v(ik) = EXP(-lambda*my_rmsd)
5253         DO iat = 1, rmsd_atom
5254            i = iatom(iat)
5255            ds1v(1, iat, ik) = drmsd(1, i)*s1v(ik)
5256            ds1v(2, iat, ik) = drmsd(2, i)*s1v(ik)
5257            ds1v(3, iat, ik) = drmsd(3, i)*s1v(ik)
5258         END DO
5259      END DO
5260
5261      s1 = accurate_sum(s1v(:))
5262      DO iat = 1, rmsd_atom
5263         ds1(1, iat) = accurate_sum(ds1v(1, iat, :))
5264         ds1(2, iat) = accurate_sum(ds1v(2, iat, :))
5265         ds1(3, iat) = accurate_sum(ds1v(3, iat, :))
5266      END DO
5267      colvar%ss = -1.0_dp/lambda*LOG(s1)
5268
5269      ALLOCATE (fi(3, rmsd_atom))
5270
5271      DO iat = 1, rmsd_atom
5272         fi(:, iat) = ds1(:, iat)/s1
5273         CALL put_derivative(colvar, iat, fi(:, iat))
5274      END DO
5275
5276      DEALLOCATE (fi)
5277      DEALLOCATE (r0)
5278      DEALLOCATE (r)
5279      DEALLOCATE (riat)
5280      DEALLOCATE (s1v)
5281      DEALLOCATE (ds1v)
5282      DEALLOCATE (ds1)
5283      DEALLOCATE (drmsd)
5284      DEALLOCATE (weight)
5285
5286   END SUBROUTINE dpath_rmsd
5287
5288! **************************************************************************************************
5289!> \brief evaluates the force due to population colvar
5290!> \param colvar ...
5291!> \param cell ...
5292!> \param subsys ...
5293!> \param particles ...
5294!> \date  01.2009
5295!> \author fsterpone
5296! **************************************************************************************************
5297   SUBROUTINE population_colvar(colvar, cell, subsys, particles)
5298      TYPE(colvar_type), POINTER                         :: colvar
5299      TYPE(cell_type), POINTER                           :: cell
5300      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
5301      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
5302         POINTER                                         :: particles
5303
5304      CHARACTER(len=*), PARAMETER :: routineN = 'population_colvar', &
5305         routineP = moduleN//':'//routineN
5306
5307      INTEGER                                            :: i, ii, jj, n_atoms_from, n_atoms_to, &
5308                                                            ndcrd, nncrd
5309      REAL(dp) :: dfunc, dfunc_coord, ftmp(3), func, func_coord, inv_n_atoms_from, invden, n_0, &
5310         ncoord, norm, num, population, r12, r_0, rdist, sigma, ss(3), xij(3)
5311      REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: ftmp_coord
5312      REAL(dp), DIMENSION(3)                             :: xpi, xpj
5313      TYPE(particle_list_type), POINTER                  :: particles_i
5314      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
5315
5316! If we defined the coordination number with KINDS then we have still
5317! to fill few missing informations...
5318
5319      NULLIFY (particles_i)
5320      CPASSERT(colvar%type_id == population_colvar_id)
5321      IF (PRESENT(particles)) THEN
5322         my_particles => particles
5323      ELSE
5324         CPASSERT(PRESENT(subsys))
5325         CALL cp_subsys_get(subsys, particles=particles_i)
5326         my_particles => particles_i%els
5327      END IF
5328      n_atoms_to = colvar%population_param%n_atoms_to
5329      n_atoms_from = colvar%population_param%n_atoms_from
5330      nncrd = colvar%population_param%nncrd
5331      ndcrd = colvar%population_param%ndcrd
5332      r_0 = colvar%population_param%r_0
5333      n_0 = colvar%population_param%n0
5334      sigma = colvar%population_param%sigma
5335
5336      ALLOCATE (ftmp_coord(3, n_atoms_to))
5337      ftmp_coord = 0.0_dp
5338
5339      ncoord = 0.0_dp
5340      population = 0.0_dp
5341
5342      colvar%dsdr = 0.0_dp
5343      inv_n_atoms_from = 1.0_dp/REAL(n_atoms_from, KIND=dp)
5344
5345      norm = SQRT(pi*2.0_dp)*sigma
5346      norm = 1/norm
5347
5348      DO ii = 1, n_atoms_from
5349         i = colvar%population_param%i_at_from(ii)
5350         CALL get_coordinates(colvar, i, xpi, my_particles)
5351         DO jj = 1, n_atoms_to
5352            i = colvar%population_param%i_at_to(jj)
5353            CALL get_coordinates(colvar, i, xpj, my_particles)
5354            ss = MATMUL(cell%h_inv, xpi(:) - xpj(:))
5355            ss = ss - NINT(ss)
5356            xij = MATMUL(cell%hmat, ss)
5357            r12 = SQRT(xij(1)**2 + xij(2)**2 + xij(3)**2)
5358            IF (r12 < 1.0e-8_dp) CYCLE
5359            rdist = r12/r_0
5360            num = (1.0_dp - rdist**nncrd)
5361            invden = 1.0_dp/(1.0_dp - rdist**ndcrd)
5362            func_coord = num*invden
5363            dfunc_coord = (-nncrd*rdist**(nncrd - 1)*invden &
5364                           + num*(invden)**2*ndcrd*rdist**(ndcrd - 1))/(r12*r_0)
5365
5366            ncoord = ncoord + func_coord
5367            ftmp_coord(1, jj) = dfunc_coord*xij(1)
5368            ftmp_coord(2, jj) = dfunc_coord*xij(2)
5369            ftmp_coord(3, jj) = dfunc_coord*xij(3)
5370         END DO
5371
5372         func = EXP(-(ncoord - n_0)**2/(2.0_dp*sigma*sigma))
5373         dfunc = -func*(ncoord - n_0)/(sigma*sigma)
5374
5375         population = population + norm*func
5376         DO jj = 1, n_atoms_to
5377            ftmp(1) = ftmp_coord(1, jj)*dfunc
5378            ftmp(2) = ftmp_coord(2, jj)*dfunc
5379            ftmp(3) = ftmp_coord(3, jj)*dfunc
5380            CALL put_derivative(colvar, ii, ftmp)
5381            ftmp(1) = -ftmp_coord(1, jj)*dfunc
5382            ftmp(2) = -ftmp_coord(2, jj)*dfunc
5383            ftmp(3) = -ftmp_coord(3, jj)*dfunc
5384            CALL put_derivative(colvar, n_atoms_from + jj, ftmp)
5385         ENDDO
5386         ncoord = 0.0_dp
5387      ENDDO
5388      colvar%ss = population
5389   END SUBROUTINE population_colvar
5390
5391! **************************************************************************************************
5392!> \brief evaluates the force due to the gyration radius colvar
5393!>        sum_i (r_i-rcom)^2/N
5394!> \param colvar ...
5395!> \param cell ...
5396!> \param subsys ...
5397!> \param particles ...
5398!> \date  03.2009
5399!> \author MI
5400! **************************************************************************************************
5401   SUBROUTINE gyration_radius_colvar(colvar, cell, subsys, particles)
5402
5403      TYPE(colvar_type), POINTER                         :: colvar
5404      TYPE(cell_type), POINTER                           :: cell
5405      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
5406      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
5407         POINTER                                         :: particles
5408
5409      CHARACTER(len=*), PARAMETER :: routineN = 'gyration_radius_colvar', &
5410         routineP = moduleN//':'//routineN
5411
5412      INTEGER                                            :: i, ii, n_atoms
5413      REAL(dp)                                           :: dri2, func, gyration, inv_n, mass_tot, mi
5414      REAL(dp), DIMENSION(3)                             :: dfunc, dxi, ftmp, ss, xpcom, xpi
5415      TYPE(particle_list_type), POINTER                  :: particles_i
5416      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
5417
5418      NULLIFY (particles_i, my_particles)
5419      CPASSERT(colvar%type_id == gyration_colvar_id)
5420      IF (PRESENT(particles)) THEN
5421         my_particles => particles
5422      ELSE
5423         CPASSERT(PRESENT(subsys))
5424         CALL cp_subsys_get(subsys, particles=particles_i)
5425         my_particles => particles_i%els
5426      END IF
5427      n_atoms = colvar%gyration_param%n_atoms
5428      inv_n = 1.0_dp/n_atoms
5429
5430      !compute COM position
5431      xpcom = 0.0_dp
5432      mass_tot = 0.0_dp
5433      DO ii = 1, n_atoms
5434         i = colvar%gyration_param%i_at(ii)
5435         CALL get_coordinates(colvar, i, xpi, my_particles)
5436         CALL get_mass(colvar, i, mi, my_particles)
5437         xpcom(:) = xpcom(:) + xpi(:)*mi
5438         mass_tot = mass_tot + mi
5439      END DO
5440      xpcom(:) = xpcom(:)/mass_tot
5441
5442      func = 0.0_dp
5443      ftmp = 0.0_dp
5444      dfunc = 0.0_dp
5445      DO ii = 1, n_atoms
5446         i = colvar%gyration_param%i_at(ii)
5447         CALL get_coordinates(colvar, i, xpi, my_particles)
5448         ss = MATMUL(cell%h_inv, xpi(:) - xpcom(:))
5449         ss = ss - NINT(ss)
5450         dxi = MATMUL(cell%hmat, ss)
5451         dri2 = (dxi(1)**2 + dxi(2)**2 + dxi(3)**2)
5452         func = func + dri2
5453         dfunc(:) = dfunc(:) + dxi(:)
5454      END DO
5455      gyration = SQRT(inv_n*func)
5456
5457      DO ii = 1, n_atoms
5458         i = colvar%gyration_param%i_at(ii)
5459         CALL get_coordinates(colvar, i, xpi, my_particles)
5460         CALL get_mass(colvar, i, mi, my_particles)
5461         ss = MATMUL(cell%h_inv, xpi(:) - xpcom(:))
5462         ss = ss - NINT(ss)
5463         dxi = MATMUL(cell%hmat, ss)
5464         ftmp(1) = dxi(1) - dfunc(1)*mi/mass_tot
5465         ftmp(2) = dxi(2) - dfunc(2)*mi/mass_tot
5466         ftmp(3) = dxi(3) - dfunc(3)*mi/mass_tot
5467         ftmp(:) = ftmp(:)*inv_n/gyration
5468         CALL put_derivative(colvar, ii, ftmp)
5469      END DO
5470      colvar%ss = gyration
5471
5472   END SUBROUTINE gyration_radius_colvar
5473
5474! **************************************************************************************************
5475!> \brief evaluates the force due to the rmsd colvar
5476!> \param colvar ...
5477!> \param subsys ...
5478!> \param particles ...
5479!> \date  12.2009
5480!> \author MI
5481!> \note  could be extended to be used with more than 2 reference structures
5482! **************************************************************************************************
5483   SUBROUTINE rmsd_colvar(colvar, subsys, particles)
5484      TYPE(colvar_type), POINTER                         :: colvar
5485      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
5486      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
5487         POINTER                                         :: particles
5488
5489      CHARACTER(len=*), PARAMETER :: routineN = 'rmsd_colvar', routineP = moduleN//':'//routineN
5490
5491      CALL rmsd_colvar_low(colvar, subsys, particles)
5492   END SUBROUTINE rmsd_colvar
5493
5494! **************************************************************************************************
5495!> \brief  evaluates the force due to the rmsd colvar
5496!>        ss = (RMSDA-RMSDB)/(RMSDA+RMSDB)
5497!>        RMSD is calculated with respect to two reference structures, A and B,
5498!>        considering all the atoms of the system or only a subset of them,
5499!>        as selected by the input keyword LIST
5500!> \param colvar ...
5501!> \param subsys ...
5502!> \param particles ...
5503!> \date  12.2009
5504!> \par History TL 2012 (generalized to any number of frames)
5505!> \author MI
5506! **************************************************************************************************
5507   SUBROUTINE rmsd_colvar_low(colvar, subsys, particles)
5508
5509      TYPE(colvar_type), POINTER                         :: colvar
5510      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
5511      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
5512         POINTER                                         :: particles
5513
5514      CHARACTER(len=*), PARAMETER :: routineN = 'rmsd_colvar_low', &
5515         routineP = moduleN//':'//routineN
5516
5517      INTEGER                                            :: i, ii, natom, nframes
5518      REAL(kind=dp)                                      :: cv_val, f1, ftmp(3)
5519      REAL(kind=dp), ALLOCATABLE, DIMENSION(:)           :: der, r, rmsd
5520      REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :)        :: r0
5521      REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: drmsd
5522      REAL(kind=dp), DIMENSION(:), POINTER               :: weights
5523      TYPE(particle_list_type), POINTER                  :: particles_i
5524      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
5525
5526      NULLIFY (my_particles, particles_i, weights)
5527      CPASSERT(colvar%type_id == rmsd_colvar_id)
5528      IF (PRESENT(particles)) THEN
5529         my_particles => particles
5530      ELSE
5531         CPASSERT(PRESENT(subsys))
5532         CALL cp_subsys_get(subsys, particles=particles_i)
5533         my_particles => particles_i%els
5534      END IF
5535
5536      natom = SIZE(my_particles)
5537      nframes = colvar%rmsd_param%nr_frames
5538      ALLOCATE (drmsd(3, natom, nframes))
5539      drmsd = 0.0_dp
5540
5541      ALLOCATE (r0(3*natom, nframes))
5542      ALLOCATE (rmsd(nframes))
5543      ALLOCATE (der(nframes))
5544      ALLOCATE (r(3*natom))
5545
5546      weights => colvar%rmsd_param%weights
5547      DO i = 1, natom
5548         ii = (i - 1)*3
5549         r(ii + 1) = my_particles(i)%r(1)
5550         r(ii + 2) = my_particles(i)%r(2)
5551         r(ii + 3) = my_particles(i)%r(3)
5552      END DO
5553      r0(:, :) = colvar%rmsd_param%r_ref
5554      rmsd = 0.0_dp
5555
5556      CALL rmsd3(my_particles, r, r0(:, 1), output_unit=-1, weights=weights, my_val=rmsd(1), rotate=.FALSE., drmsd3=drmsd(:, :, 1))
5557
5558      IF (nframes == 2) THEN
5559         CALL rmsd3(my_particles, r, r0(:, 2), output_unit=-1, weights=weights, &
5560                    my_val=rmsd(2), rotate=.FALSE., drmsd3=drmsd(:, :, 2))
5561
5562         f1 = 1.0_dp/(rmsd(1) + rmsd(2))
5563         ! (rmsdA-rmsdB)/(rmsdA+rmsdB)
5564         cv_val = (rmsd(1) - rmsd(2))*f1
5565         ! (rmsdA+rmsdB)^-1-(rmsdA-rmsdB)/(rmsdA+rmsdB)^2
5566         der(1) = f1 - cv_val*f1
5567         ! -(rmsdA+rmsdB)^-1-(rmsdA-rmsdB)/(rmsdA+rmsdB)^2
5568         der(2) = -f1 - cv_val*f1
5569
5570         DO i = 1, colvar%rmsd_param%n_atoms
5571            ii = colvar%rmsd_param%i_rmsd(i)
5572            IF (weights(ii) > 0.0_dp) THEN
5573               ftmp(1) = der(1)*drmsd(1, ii, 1) + der(2)*drmsd(1, ii, 2)
5574               ftmp(2) = der(1)*drmsd(2, ii, 1) + der(2)*drmsd(2, ii, 2)
5575               ftmp(3) = der(1)*drmsd(3, ii, 1) + der(2)*drmsd(3, ii, 2)
5576               CALL put_derivative(colvar, i, ftmp)
5577            END IF
5578         END DO
5579      ELSE IF (nframes == 1) THEN
5580         ! Protect in case of numerical issues (for two identical frames!)
5581         rmsd(1) = ABS(rmsd(1))
5582         cv_val = SQRT(rmsd(1))
5583         f1 = 0.0_dp
5584         IF (cv_val /= 0.0_dp) f1 = 0.5_dp/cv_val
5585         DO i = 1, colvar%rmsd_param%n_atoms
5586            ii = colvar%rmsd_param%i_rmsd(i)
5587            IF (weights(ii) > 0.0_dp) THEN
5588               ftmp(1) = f1*drmsd(1, ii, 1)
5589               ftmp(2) = f1*drmsd(2, ii, 1)
5590               ftmp(3) = f1*drmsd(3, ii, 1)
5591               CALL put_derivative(colvar, i, ftmp)
5592            END IF
5593         END DO
5594      ELSE
5595         CPABORT("RMSD implemented only for 1 and 2 reference frames!")
5596      END IF
5597      colvar%ss = cv_val
5598
5599      DEALLOCATE (der)
5600      DEALLOCATE (r0)
5601      DEALLOCATE (r)
5602      DEALLOCATE (drmsd)
5603      DEALLOCATE (rmsd)
5604
5605   END SUBROUTINE rmsd_colvar_low
5606
5607! **************************************************************************************************
5608!> \brief evaluates the force from ring puckering collective variables
5609!>   Cramer and Pople, JACS 97 1354 (1975)
5610!> \param colvar ...
5611!> \param cell ...
5612!> \param subsys ...
5613!> \param particles ...
5614!> \date 08.2012
5615!> \author JGH
5616! **************************************************************************************************
5617   SUBROUTINE ring_puckering_colvar(colvar, cell, subsys, particles)
5618      TYPE(colvar_type), POINTER                         :: colvar
5619      TYPE(cell_type), POINTER                           :: cell
5620      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: subsys
5621      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
5622         POINTER                                         :: particles
5623
5624      CHARACTER(len=*), PARAMETER :: routineN = 'ring_puckering_colvar', &
5625         routineP = moduleN//':'//routineN
5626
5627      INTEGER                                            :: i, ii, j, jj, m, nring
5628      REAL(KIND=dp)                                      :: a, at, b, da, db, ds, kr, rpxpp, svar
5629      REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: cosj, sinj, z
5630      REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: r
5631      REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: nforce, zforce
5632      REAL(KIND=dp), DIMENSION(3)                        :: ftmp, nv, r0, rp, rpp, uv
5633      REAL(KIND=dp), DIMENSION(3, 3)                     :: dnvp, dnvpp
5634      TYPE(particle_list_type), POINTER                  :: particles_i
5635      TYPE(particle_type), DIMENSION(:), POINTER         :: my_particles
5636
5637      CPASSERT(colvar%type_id == ring_puckering_colvar_id)
5638      IF (PRESENT(particles)) THEN
5639         my_particles => particles
5640      ELSE
5641         CPASSERT(PRESENT(subsys))
5642         CALL cp_subsys_get(subsys, particles=particles_i)
5643         my_particles => particles_i%els
5644      END IF
5645
5646      nring = colvar%ring_puckering_param%nring
5647      ALLOCATE (r(3, nring), z(nring), cosj(nring), sinj(nring))
5648      ALLOCATE (nforce(3, 3, nring), zforce(nring, nring, 3))
5649      DO ii = 1, nring
5650         i = colvar%ring_puckering_param%atoms(ii)
5651         CALL get_coordinates(colvar, i, r(:, ii), my_particles)
5652      END DO
5653      ! get all atoms within PBC distance of atom 1
5654      r0(:) = r(:, 1)
5655      DO ii = 1, nring
5656         r(:, ii) = pbc(r(:, ii), r0, cell)
5657      END DO
5658      !compute origin position
5659      r0 = 0.0_dp
5660      DO ii = 1, nring
5661         r0(:) = r0(:) + r(:, ii)
5662      END DO
5663      kr = 1._dp/REAL(nring, KIND=dp)
5664      r0(:) = r0(:)*kr
5665      DO ii = 1, nring
5666         r(:, ii) = r(:, ii) - r0(:)
5667      END DO
5668      ! orientation vectors
5669      rp = 0._dp
5670      rpp = 0._dp
5671      DO ii = 1, nring
5672         cosj(ii) = COS(twopi*(ii - 1)*kr)
5673         sinj(ii) = SIN(twopi*(ii - 1)*kr)
5674         rp(:) = rp(:) + r(:, ii)*sinj(ii)
5675         rpp(:) = rpp(:) + r(:, ii)*cosj(ii)
5676      END DO
5677      nv = vector_product(rp, rpp)
5678      nv = nv/SQRT(SUM(nv**2))
5679
5680      ! derivatives of normal
5681      uv = vector_product(rp, rpp)
5682      rpxpp = SQRT(SUM(uv**2))
5683      DO i = 1, 3
5684         uv = 0._dp
5685         uv(i) = 1._dp
5686         uv = vector_product(uv, rpp)/rpxpp
5687         dnvp(:, i) = uv - nv*SUM(uv*nv)
5688         uv = 0._dp
5689         uv(i) = 1._dp
5690         uv = vector_product(rp, uv)/rpxpp
5691         dnvpp(:, i) = uv - nv*SUM(uv*nv)
5692      END DO
5693      DO ii = 1, nring
5694         nforce(:, :, ii) = dnvp(:, :)*sinj(ii) + dnvpp(:, :)*cosj(ii)
5695      END DO
5696
5697      ! molecular z-coordinate
5698      DO ii = 1, nring
5699         z(ii) = SUM(r(:, ii)*nv(:))
5700      END DO
5701      ! z-force
5702      DO ii = 1, nring
5703         DO jj = 1, nring
5704            IF (ii == jj) THEN
5705               zforce(ii, jj, :) = nv
5706            ELSE
5707               zforce(ii, jj, :) = 0._dp
5708            END IF
5709            DO i = 1, 3
5710               DO j = 1, 3
5711                  zforce(ii, jj, i) = zforce(ii, jj, i) + r(j, ii)*nforce(j, i, jj)
5712               END DO
5713            END DO
5714         END DO
5715      END DO
5716
5717      IF (colvar%ring_puckering_param%iq == 0) THEN
5718         ! total puckering amplitude
5719         svar = SQRT(SUM(z**2))
5720         DO ii = 1, nring
5721            ftmp = 0._dp
5722            DO jj = 1, nring
5723               ftmp(:) = ftmp(:) + zforce(jj, ii, :)*z(jj)
5724            END DO
5725            ftmp = ftmp/svar
5726            CALL put_derivative(colvar, ii, ftmp)
5727         END DO
5728      ELSE
5729         m = ABS(colvar%ring_puckering_param%iq)
5730         CPASSERT(m /= 1)
5731         IF (MOD(nring, 2) == 0 .AND. colvar%ring_puckering_param%iq == nring/2) THEN
5732            ! single puckering amplitude
5733            svar = 0._dp
5734            DO ii = 1, nring
5735               IF (MOD(ii, 2) == 0) THEN
5736                  svar = svar - z(ii)
5737               ELSE
5738                  svar = svar + z(ii)
5739               END IF
5740            END DO
5741            svar = svar*SQRT(kr)
5742            DO ii = 1, nring
5743               ftmp = 0._dp
5744               DO jj = 1, nring
5745                  IF (MOD(jj, 2) == 0) THEN
5746                     ftmp(:) = ftmp(:) - zforce(jj, ii, :)*SQRT(kr)
5747                  ELSE
5748                     ftmp(:) = ftmp(:) + zforce(jj, ii, :)*SQRT(kr)
5749                  END IF
5750               END DO
5751               CALL put_derivative(colvar, ii, -ftmp)
5752            END DO
5753         ELSE
5754            CPASSERT(m <= (nring - 1)/2)
5755            a = 0._dp
5756            b = 0._dp
5757            DO ii = 1, nring
5758               a = a + z(ii)*COS(twopi*m*(ii - 1)*kr)
5759               b = b - z(ii)*SIN(twopi*m*(ii - 1)*kr)
5760            END DO
5761            a = a*SQRT(2._dp*kr)
5762            b = b*SQRT(2._dp*kr)
5763            IF (colvar%ring_puckering_param%iq > 0) THEN
5764               ! puckering amplitude
5765               svar = SQRT(a*a + b*b)
5766               da = a/svar
5767               db = b/svar
5768            ELSE
5769               ! puckering phase angle
5770               at = ATAN2(a, b)
5771               IF (at > pi/2._dp) THEN
5772                  svar = 2.5_dp*pi - at
5773               ELSE
5774                  svar = 0.5_dp*pi - at
5775               END IF
5776               da = -b/(a*a + b*b)
5777               db = a/(a*a + b*b)
5778            END IF
5779            DO jj = 1, nring
5780               ftmp = 0._dp
5781               DO ii = 1, nring
5782                  ds = da*COS(twopi*m*(ii - 1)*kr)
5783                  ds = ds - db*SIN(twopi*m*(ii - 1)*kr)
5784                  ftmp(:) = ftmp(:) + ds*SQRT(2._dp*kr)*zforce(ii, jj, :)
5785               END DO
5786               CALL put_derivative(colvar, jj, ftmp)
5787            END DO
5788         END IF
5789      END IF
5790
5791      colvar%ss = svar
5792
5793      DEALLOCATE (r, z, cosj, sinj, nforce, zforce)
5794
5795   END SUBROUTINE ring_puckering_colvar
5796
5797! **************************************************************************************************
5798!> \brief used to print reaction_path function values on an arbitrary dimensional grid
5799!> \param iw1 ...
5800!> \param ncol ...
5801!> \param f_vals ...
5802!> \param v_count ...
5803!> \param gp ...
5804!> \param grid_sp ...
5805!> \param step_size ...
5806!> \param istart ...
5807!> \param iend ...
5808!> \param s1v ...
5809!> \param s1 ...
5810!> \param p_bounds ...
5811!> \param lambda ...
5812!> \param ifunc ...
5813!> \param nconf ...
5814!> \return ...
5815!> \author fschiff
5816! **************************************************************************************************
5817   RECURSIVE FUNCTION rec_eval_grid(iw1, ncol, f_vals, v_count, &
5818                                    gp, grid_sp, step_size, istart, iend, s1v, s1, p_bounds, lambda, ifunc, nconf) RESULT(k)
5819      INTEGER                                            :: iw1, ncol
5820      REAL(dp), DIMENSION(:, :), POINTER                 :: f_vals
5821      INTEGER                                            :: v_count
5822      REAL(dp), DIMENSION(:), POINTER                    :: gp, grid_sp
5823      REAL(dp)                                           :: step_size
5824      INTEGER                                            :: istart, iend
5825      REAL(dp), DIMENSION(:, :), POINTER                 :: s1v
5826      REAL(dp), DIMENSION(:), POINTER                    :: s1
5827      INTEGER, DIMENSION(:, :), POINTER                  :: p_bounds
5828      REAL(dp)                                           :: lambda
5829      INTEGER                                            :: ifunc, nconf, k
5830
5831      INTEGER                                            :: count1, i
5832
5833      k = 1
5834      IF (v_count .LT. ncol) THEN
5835         count1 = v_count + 1
5836         DO i = p_bounds(1, count1), p_bounds(2, count1)
5837            gp(count1) = REAL(i, KIND=dp)*grid_sp(count1)
5838            k = rec_eval_grid(iw1, ncol, f_vals, count1, gp, grid_sp, step_size, &
5839                              istart, iend, s1v, s1, p_bounds, lambda, ifunc, nconf)
5840         END DO
5841      ELSE IF (v_count == ncol .AND. ifunc == 1) THEN
5842         DO i = istart, iend
5843            s1v(1, i) = REAL(i, kind=dp)*step_size*EXP(-lambda*DOT_PRODUCT(gp(:) - f_vals(:, i), &
5844                                                                           gp(:) - f_vals(:, i)))
5845            s1v(2, i) = EXP(-lambda*DOT_PRODUCT(gp(:) - f_vals(:, i), gp(:) - f_vals(:, i)))
5846         END DO
5847         DO i = 1, 2
5848            s1(i) = accurate_sum(s1v(i, :))
5849         END DO
5850         WRITE (iw1, '(5F10.5)') gp(:), s1(1)/s1(2)/REAL(nconf - 1, dp)
5851      ELSE IF (v_count == ncol .AND. ifunc == 2) THEN
5852         DO i = istart, iend
5853            s1v(1, i) = EXP(-lambda*DOT_PRODUCT(gp(:) - f_vals(:, i), gp(:) - f_vals(:, i)))
5854         END DO
5855         s1(1) = accurate_sum(s1v(1, :))
5856
5857         WRITE (iw1, '(5F10.5)') gp(:), -lambda*LOG(s1(1))
5858      END IF
5859   END FUNCTION rec_eval_grid
5860
5861! **************************************************************************************************
5862!> \brief  Reads the coordinates of reference configurations given in input
5863!>         either as xyz files or in &COORD section
5864!> \param frame_section ...
5865!> \param para_env ...
5866!> \param nr_frames ...
5867!> \param r_ref ...
5868!> \param n_atoms ...
5869!> \date 01.2010
5870!> \author MI
5871! **************************************************************************************************
5872   SUBROUTINE read_frames(frame_section, para_env, nr_frames, r_ref, n_atoms)
5873
5874      TYPE(section_vals_type), POINTER                   :: frame_section
5875      TYPE(cp_para_env_type), POINTER                    :: para_env
5876      INTEGER, INTENT(IN)                                :: nr_frames
5877      REAL(dp), DIMENSION(:, :), POINTER                 :: r_ref
5878      INTEGER, INTENT(OUT)                               :: n_atoms
5879
5880      CHARACTER(len=*), PARAMETER :: routineN = 'read_frames', routineP = moduleN//':'//routineN
5881
5882      CHARACTER(LEN=default_path_length)                 :: filename
5883      CHARACTER(LEN=default_string_length)               :: dummy_char
5884      INTEGER                                            :: i, j, natom
5885      LOGICAL                                            :: explicit, my_end
5886      REAL(KIND=dp), DIMENSION(:), POINTER               :: rptr
5887      TYPE(cp_parser_type), POINTER                      :: parser
5888      TYPE(section_vals_type), POINTER                   :: coord_section
5889
5890      NULLIFY (rptr)
5891
5892      DO i = 1, nr_frames
5893         coord_section => section_vals_get_subs_vals(frame_section, "COORD", i_rep_section=i)
5894         CALL section_vals_get(coord_section, explicit=explicit)
5895         ! Cartesian Coordinates
5896         IF (explicit) THEN
5897            CALL section_vals_val_get(coord_section, "_DEFAULT_KEYWORD_", &
5898                                      n_rep_val=natom)
5899            IF (i == 1) THEN
5900               ALLOCATE (r_ref(3*natom, nr_frames))
5901               n_atoms = natom
5902            ELSE
5903               CPASSERT(3*natom == SIZE(r_ref, 1))
5904            END IF
5905            DO j = 1, natom
5906               CALL section_vals_val_get(coord_section, "_DEFAULT_KEYWORD_", &
5907                                         i_rep_val=j, r_vals=rptr)
5908               r_ref((j - 1)*3 + 1:(j - 1)*3 + 3, i) = rptr(1:3)
5909            END DO ! natom
5910         ELSE
5911            CALL section_vals_val_get(frame_section, "COORD_FILE_NAME", i_rep_section=i, c_val=filename)
5912            CPASSERT(TRIM(filename) /= "")
5913            NULLIFY (parser)
5914            ALLOCATE (rptr(3))
5915            CALL parser_create(parser, filename, para_env=para_env, parse_white_lines=.TRUE.)
5916            CALL parser_get_next_line(parser, 1)
5917            ! Start parser
5918            CALL parser_get_object(parser, natom)
5919            CALL parser_get_next_line(parser, 1)
5920            IF (i == 1) THEN
5921               ALLOCATE (r_ref(3*natom, nr_frames))
5922               n_atoms = natom
5923            ELSE
5924               CPASSERT(3*natom == SIZE(r_ref, 1))
5925            END IF
5926            DO j = 1, natom
5927               ! Atom coordinates
5928               CALL parser_get_next_line(parser, 1, at_end=my_end)
5929               IF (my_end) &
5930                  CALL cp_abort(__LOCATION__, &
5931                                "Number of lines in XYZ format not equal to the number of atoms."// &
5932                                " Error in XYZ format for COORD_A (CV rmsd). Very probably the"// &
5933                                " line with title is missing or is empty. Please check the XYZ file and rerun your job!")
5934               READ (parser%input_line, *) dummy_char, rptr(1:3)
5935               r_ref((j - 1)*3 + 1, i) = cp_unit_to_cp2k(rptr(1), "angstrom")
5936               r_ref((j - 1)*3 + 2, i) = cp_unit_to_cp2k(rptr(2), "angstrom")
5937               r_ref((j - 1)*3 + 3, i) = cp_unit_to_cp2k(rptr(3), "angstrom")
5938            END DO ! natom
5939            CALL parser_release(parser)
5940            DEALLOCATE (rptr)
5941         END IF
5942      END DO ! nr_frames
5943
5944   END SUBROUTINE read_frames
5945
5946! **************************************************************************************************
5947!> \brief evaluates the collective variable associated with a hydrogen bond
5948!> \param colvar ...
5949!> \param cell ...
5950!> \param subsys ...
5951!> \param particles ...
5952!> \param qs_env should be removed
5953!> \author alin m elena
5954! **************************************************************************************************
5955   SUBROUTINE Wc_colvar(colvar, cell, subsys, particles, qs_env)
5956      TYPE(colvar_type), POINTER               :: colvar
5957      TYPE(cell_type), POINTER                 :: cell
5958      TYPE(cp_subsys_type), OPTIONAL, POINTER  :: subsys
5959      TYPE(particle_type), DIMENSION(:), &
5960         OPTIONAL, POINTER                      :: particles
5961      TYPE(qs_environment_type), POINTER, OPTIONAL       :: qs_env
5962
5963      CHARACTER(len=*), PARAMETER :: routineN = 'Wc_colvar', &
5964                                     routineP = moduleN//':'//routineN
5965
5966      INTEGER                                  :: Od, H, Oa
5967      REAL(dp)                                 :: rOd(3), rOa(3), rH(3), &
5968                                                  x, y, s(3), xv(3), dmin, amin
5969      INTEGER                                  :: idmin, iamin, i, j
5970      TYPE(particle_list_type), POINTER        :: particles_i
5971      TYPE(particle_type), DIMENSION(:), &
5972         POINTER                                :: my_particles
5973      TYPE(wannier_centres_type), DIMENSION(:), POINTER :: wc
5974      INTEGER, ALLOCATABLE                     :: wcai(:), wcdi(:)
5975      INTEGER                                  :: nwca, nwcd
5976      REAL(dp)                                 :: rcut
5977
5978      NULLIFY (particles_i, wc)
5979
5980      CPASSERT(colvar%type_id == Wc_colvar_id)
5981      IF (PRESENT(particles)) THEN
5982         my_particles => particles
5983      ELSE
5984         CPASSERT(PRESENT(subsys))
5985         CALL cp_subsys_get(subsys, particles=particles_i)
5986         my_particles => particles_i%els
5987      END IF
5988      CALL get_qs_env(qs_env, WannierCentres=wc)
5989      rcut = colvar%Wc%rcut ! distances are in bohr as far as I remember
5990      Od = colvar%Wc%ids(1)
5991      H = colvar%Wc%ids(2)
5992      Oa = colvar%Wc%ids(3)
5993      CALL get_coordinates(colvar, Od, rOd, my_particles)
5994      CALL get_coordinates(colvar, H, rH, my_particles)
5995      CALL get_coordinates(colvar, Oa, rOa, my_particles)
5996      ALLOCATE (wcai(SIZE(wc(1)%WannierHamDiag)))
5997      ALLOCATE (wcdi(SIZE(wc(1)%WannierHamDiag)))
5998      nwca = 0
5999      nwcd = 0
6000      DO j = 1, SIZE(wc(1)%WannierHamDiag)
6001         x = distance(rOd - wc(1)%centres(:, j))
6002         y = distance(rOa - wc(1)%centres(:, j))
6003         IF (x < rcut) THEN
6004            nwcd = nwcd + 1
6005            wcdi(nwcd) = j
6006            CYCLE
6007         ENDIF
6008         IF (y < rcut) THEN
6009            nwca = nwca + 1
6010            wcai(nwca) = j
6011         ENDIF
6012      ENDDO
6013
6014      dmin = distance(rH - wc(1)%centres(:, wcdi(1)))
6015      amin = distance(rH - wc(1)%centres(:, wcai(1)))
6016      idmin = wcdi(1)
6017      iamin = wcai(1)
6018      !dmin constains the smallest numer, amin the next smallest
6019      DO i = 2, nwcd
6020         x = distance(rH - wc(1)%centres(:, wcdi(i)))
6021         IF (x < dmin) THEN
6022            dmin = x
6023            idmin = wcdi(i)
6024         ENDIF
6025      ENDDO
6026      DO i = 2, nwca
6027         x = distance(rH - wc(1)%centres(:, wcai(i)))
6028         IF (x < amin) THEN
6029            amin = x
6030            iamin = wcai(i)
6031         ENDIF
6032      ENDDO
6033!     zero=0.0_dp
6034!     CALL put_derivative(colvar, 1, zero)
6035!     CALL put_derivative(colvar, 2,zero)
6036!     CALL put_derivative(colvar, 3, zero)
6037
6038!     write(*,'(2(i0,1x),4(f16.8,1x))')idmin,iamin,wc(1)%WannierHamDiag(idmin),wc(1)%WannierHamDiag(iamin),dmin,amin
6039      colvar%ss = wc(1)%WannierHamDiag(idmin) - wc(1)%WannierHamDiag(iamin)
6040      DEALLOCATE (wcai)
6041      DEALLOCATE (wcdi)
6042
6043   CONTAINS
6044! **************************************************************************************************
6045!> \brief ...
6046!> \param rij ...
6047!> \return ...
6048! **************************************************************************************************
6049      REAL(dp) FUNCTION distance(rij)
6050      REAL(dp), INTENT(in)                               :: rij(3)
6051
6052         s = MATMUL(cell%h_inv, rij)
6053         s = s - NINT(s)
6054         xv = MATMUL(cell%hmat, s)
6055         distance = SQRT(DOT_PRODUCT(xv, xv))
6056      END FUNCTION distance
6057
6058   END SUBROUTINE Wc_colvar
6059
6060! **************************************************************************************************
6061!> \brief evaluates the collective variable associated with a hydrogen bond wire
6062!> \param colvar ...
6063!> \param cell ...
6064!> \param subsys ...
6065!> \param particles ...
6066!> \param qs_env ...
6067!> \author alin m elena
6068! **************************************************************************************************
6069   SUBROUTINE HBP_colvar(colvar, cell, subsys, particles, qs_env)
6070      TYPE(colvar_type), POINTER               :: colvar
6071      TYPE(cell_type), POINTER                 :: cell
6072      TYPE(cp_subsys_type), OPTIONAL, POINTER  :: subsys
6073      TYPE(particle_type), DIMENSION(:), &
6074         OPTIONAL, POINTER                      :: particles
6075      TYPE(qs_environment_type), POINTER, OPTIONAL       :: qs_env ! optional just because I am lazy... but I should get rid of it...
6076
6077      CHARACTER(len=*), PARAMETER :: routineN = 'HBP_colvar', &
6078                                     routineP = moduleN//':'//routineN
6079
6080      INTEGER                                  :: Od, H, Oa
6081      REAL(dp)                                 :: rOd(3), rOa(3), rH(3), &
6082                                                  x, y, s(3), xv(3), dmin, amin
6083      INTEGER                                  :: idmin, iamin, i, j, il, output_unit
6084      TYPE(particle_list_type), POINTER        :: particles_i
6085      TYPE(particle_type), DIMENSION(:), &
6086         POINTER                                :: my_particles
6087      TYPE(wannier_centres_type), &
6088         DIMENSION(:), POINTER :: wc
6089      INTEGER, ALLOCATABLE                     :: wcai(:), wcdi(:)
6090      INTEGER                                  :: nwca, nwcd
6091      REAL(dp)                                 :: rcut
6092
6093      NULLIFY (particles_i, wc)
6094      output_unit = cp_logger_get_default_io_unit()
6095
6096      CPASSERT(colvar%type_id == HBP_colvar_id)
6097      IF (PRESENT(particles)) THEN
6098         my_particles => particles
6099      ELSE
6100         CPASSERT(PRESENT(subsys))
6101         CALL cp_subsys_get(subsys, particles=particles_i)
6102         my_particles => particles_i%els
6103      END IF
6104      CALL get_qs_env(qs_env, WannierCentres=wc)
6105      rcut = colvar%HBP%rcut ! distances are in bohr as far as I remember
6106      ALLOCATE (wcai(SIZE(wc(1)%WannierHamDiag)))
6107      ALLOCATE (wcdi(SIZE(wc(1)%WannierHamDiag)))
6108      colvar%ss = 0.0_dp
6109      DO il = 1, colvar%HBP%nPoints
6110         Od = colvar%HBP%ids(il, 1)
6111         H = colvar%HBP%ids(il, 2)
6112         Oa = colvar%HBP%ids(il, 3)
6113         CALL get_coordinates(colvar, Od, rOd, my_particles)
6114         CALL get_coordinates(colvar, H, rH, my_particles)
6115         CALL get_coordinates(colvar, Oa, rOa, my_particles)
6116         nwca = 0
6117         nwcd = 0
6118         DO j = 1, SIZE(wc(1)%WannierHamDiag)
6119            x = distance(rOd - wc(1)%centres(:, j))
6120            y = distance(rOa - wc(1)%centres(:, j))
6121            IF (x < rcut) THEN
6122               nwcd = nwcd + 1
6123               wcdi(nwcd) = j
6124               CYCLE
6125            ENDIF
6126            IF (y < rcut) THEN
6127               nwca = nwca + 1
6128               wcai(nwca) = j
6129            ENDIF
6130         ENDDO
6131
6132         dmin = distance(rH - wc(1)%centres(:, wcdi(1)))
6133         amin = distance(rH - wc(1)%centres(:, wcai(1)))
6134         idmin = wcdi(1)
6135         iamin = wcai(1)
6136         !dmin constains the smallest numer, amin the next smallest
6137         DO i = 2, nwcd
6138            x = distance(rH - wc(1)%centres(:, wcdi(i)))
6139            IF (x < dmin) THEN
6140               dmin = x
6141               idmin = wcdi(i)
6142            ENDIF
6143         ENDDO
6144         DO i = 2, nwca
6145            x = distance(rH - wc(1)%centres(:, wcai(i)))
6146            IF (x < amin) THEN
6147               amin = x
6148               iamin = wcai(i)
6149            ENDIF
6150         ENDDO
6151         colvar%HBP%ewc(il) = colvar%HBP%shift + wc(1)%WannierHamDiag(idmin) - wc(1)%WannierHamDiag(iamin)
6152         colvar%ss = colvar%ss + colvar%HBP%shift + wc(1)%WannierHamDiag(idmin) - wc(1)%WannierHamDiag(iamin)
6153      ENDDO
6154      IF (output_unit > 0) THEN
6155         DO il = 1, colvar%HBP%nPoints
6156            WRITE (output_unit, '(a,1(f16.8,1x))') "HBP| = ", colvar%HBP%ewc(il)
6157         ENDDO
6158         WRITE (output_unit, '(a,1(f16.8,1x))') "HBP|\theta(x) = ", colvar%ss
6159      ENDIF
6160      DEALLOCATE (wcai)
6161      DEALLOCATE (wcdi)
6162
6163   CONTAINS
6164! **************************************************************************************************
6165!> \brief ...
6166!> \param rij ...
6167!> \return ...
6168! **************************************************************************************************
6169      REAL(dp) FUNCTION distance(rij)
6170      REAL(dp), INTENT(in)                               :: rij(3)
6171
6172         s = MATMUL(cell%h_inv, rij)
6173         s = s - NINT(s)
6174         xv = MATMUL(cell%hmat, s)
6175         distance = SQRT(DOT_PRODUCT(xv, xv))
6176      END FUNCTION distance
6177
6178   END SUBROUTINE HBP_colvar
6179
6180END MODULE colvar_methods
6181