LCOV - code coverage report
Current view: top level - src - colvar_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:c24029e) Lines: 80.9 % 3500 2831
Test Date: 2026-07-04 06:36:57 Functions: 89.6 % 48 43

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

Generated by: LCOV version 2.0-1