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

Generated by: LCOV version 2.0-1