LCOV - code coverage report
Current view: top level - src - colvar_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 81.1 % 3622 2937
Test Date: 2026-11-04 00:58:17 Functions: 90.0 % 50 45

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

Generated by: LCOV version 2.0-1