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

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

Generated by: LCOV version 2.0-1