LCOV - code coverage report
Current view: top level - src - colvar_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 80.9 % 3495 2828
Test Date: 2025-12-04 06:27:48 Functions: 89.6 % 48 43

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

Generated by: LCOV version 2.0-1