LCOV - code coverage report
Current view: top level - src - topology_amber.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:b310db4) Lines: 96.2 % 959 923
Test Date: 2026-10-23 01:10:43 Functions: 100.0 % 17 17

            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  Handles all functions used to read and interpret AMBER coordinates
      10              : !>         and topology files
      11              : !>
      12              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
      13              : ! **************************************************************************************************
      14              : MODULE topology_amber
      15              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      16              :                                               cp_logger_type,&
      17              :                                               cp_to_string
      18              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      19              :                                               cp_print_key_unit_nr
      20              :    USE cp_parser_methods,               ONLY: parser_get_next_line,&
      21              :                                               parser_get_object,&
      22              :                                               parser_search_string,&
      23              :                                               parser_test_next_token
      24              :    USE cp_parser_types,                 ONLY: cp_parser_type,&
      25              :                                               parser_create,&
      26              :                                               parser_release
      27              :    USE cp_units,                        ONLY: cp_unit_to_cp2k
      28              :    USE force_field_types,               ONLY: amber_info_type
      29              :    USE input_cp2k_restarts_util,        ONLY: section_velocity_val_set
      30              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      31              :                                               section_vals_type
      32              :    USE kinds,                           ONLY: default_string_length,&
      33              :                                               dp
      34              :    USE memory_utilities,                ONLY: reallocate
      35              :    USE message_passing,                 ONLY: mp_para_env_type
      36              :    USE particle_types,                  ONLY: particle_type
      37              :    USE qmmm_ff_fist,                    ONLY: qmmm_ff_precond_only_qm
      38              :    USE string_table,                    ONLY: id2str,&
      39              :                                               s2s,&
      40              :                                               str2id
      41              :    USE topology_generate_util,          ONLY: topology_generate_molname
      42              :    USE topology_types,                  ONLY: atom_info_type,&
      43              :                                               connectivity_info_type,&
      44              :                                               topology_parameters_type
      45              :    USE util,                            ONLY: sort
      46              : #include "./base/base_uses.f90"
      47              : 
      48              :    IMPLICIT NONE
      49              : 
      50              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'topology_amber'
      51              :    REAL(KIND=dp), PARAMETER, PRIVATE    :: amber_conv_factor = 20.4550_dp, &
      52              :                                            amber_conv_charge = 18.2223_dp
      53              :    INTEGER, PARAMETER, PRIVATE          :: buffer_size = 1
      54              : 
      55              :    PRIVATE
      56              :    PUBLIC :: read_coordinate_crd, read_connectivity_amber, rdparm_amber_8
      57              : 
      58              :    ! Reading Amber sections routines
      59              :    INTERFACE rd_amber_section
      60              :       MODULE PROCEDURE rd_amber_section_i1, rd_amber_section_c1, rd_amber_section_r1, &
      61              :          rd_amber_section_i3, rd_amber_section_i4, rd_amber_section_i5
      62              :    END INTERFACE
      63              : 
      64              : CONTAINS
      65              : 
      66              : ! **************************************************************************************************
      67              : !> \brief  Reads the `coord' version generated by the PARM or LEaP programs, as
      68              : !>         well as the  `restrt' version, resulting from  energy minimization or
      69              : !>         molecular dynamics in SANDER or GIBBS. It may contain velocity and
      70              : !>         periodic box information.
      71              : !>
      72              : !>         Official Format from the AMBER homepage
      73              : !>         FORMAT(20A4) ITITL
      74              : !>           ITITL  : the title of the current run, from the AMBER
      75              : !>                    parameter/topology file
      76              : !>
      77              : !>         FORMAT(I5,5E15.7) NATOM,TIME
      78              : !>           NATOM  : total number of atoms in coordinate file
      79              : !>           TIME   : option, current time in the simulation (picoseconds)
      80              : !>
      81              : !>         FORMAT(6F12.7) (X(i), Y(i), Z(i), i = 1,NATOM)
      82              : !>           X,Y,Z  : coordinates
      83              : !>
      84              : !>         IF dynamics
      85              : !>
      86              : !>         FORMAT(6F12.7) (VX(i), VY(i), VZ(i), i = 1,NATOM)
      87              : !>           VX,VY,VZ : velocities (units: Angstroms per 1/20.455 ps)
      88              : !>
      89              : !>         IF constant pressure (in 4.1, also constant volume)
      90              : !>
      91              : !>         FORMAT(6F12.7) BOX(1), BOX(2), BOX(3)
      92              : !>           BOX    : size of the periodic box
      93              : !>
      94              : !>
      95              : !> \param topology ...
      96              : !> \param para_env ...
      97              : !> \param subsys_section ...
      98              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
      99              : ! **************************************************************************************************
     100          104 :    SUBROUTINE read_coordinate_crd(topology, para_env, subsys_section)
     101              :       TYPE(topology_parameters_type)                     :: topology
     102              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     103              :       TYPE(section_vals_type), POINTER                   :: subsys_section
     104              : 
     105              :       CHARACTER(len=*), PARAMETER :: routineN = 'read_coordinate_crd'
     106              : 
     107              :       CHARACTER(LEN=default_string_length)               :: string
     108              :       INTEGER                                            :: handle, iw, j, natom
     109              :       LOGICAL                                            :: my_end, setup_velocities
     110           26 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: velocity
     111              :       TYPE(atom_info_type), POINTER                      :: atom_info
     112              :       TYPE(cp_logger_type), POINTER                      :: logger
     113              :       TYPE(cp_parser_type)                               :: parser
     114              :       TYPE(section_vals_type), POINTER                   :: velocity_section
     115              : 
     116           26 :       NULLIFY (logger, velocity)
     117           52 :       logger => cp_get_default_logger()
     118              :       iw = cp_print_key_unit_nr(logger, subsys_section, "PRINT%TOPOLOGY_INFO/CRD_INFO", &
     119           26 :                                 extension=".subsysLog")
     120           26 :       CALL timeset(routineN, handle)
     121              : 
     122           26 :       atom_info => topology%atom_info
     123           26 :       IF (iw > 0) WRITE (iw, *) "    Reading in CRD file ", TRIM(topology%coord_file_name)
     124              : 
     125              :       ! Title Section
     126           26 :       IF (iw > 0) WRITE (iw, '(T2,A)') 'CRD_INFO| Parsing the TITLE section'
     127           26 :       CALL parser_create(parser, topology%coord_file_name, para_env=para_env)
     128           26 :       CALL parser_get_next_line(parser, 1)
     129              :       ! Title may be missing
     130           26 :       IF (parser_test_next_token(parser) == "STR") THEN
     131           20 :          CALL parser_get_object(parser, string, string_length=default_string_length)
     132           20 :          IF (iw > 0) WRITE (iw, '(T2,A)') 'CRD_INFO| '//TRIM(string)
     133              :          ! Natom and Time (which we ignore)
     134           46 :          CALL parser_get_next_line(parser, 1)
     135              :       END IF
     136           26 :       CALL parser_get_object(parser, natom)
     137           26 :       topology%natoms = natom
     138           26 :       IF (iw > 0) WRITE (iw, '(T2,A,I0)') 'CRD_INFO| Number of atoms: ', natom
     139           26 :       CALL reallocate(atom_info%id_molname, 1, natom)
     140           26 :       CALL reallocate(atom_info%id_resname, 1, natom)
     141           26 :       CALL reallocate(atom_info%resid, 1, natom)
     142           26 :       CALL reallocate(atom_info%id_atmname, 1, natom)
     143           26 :       CALL reallocate(atom_info%r, 1, 3, 1, natom)
     144           26 :       CALL reallocate(atom_info%atm_mass, 1, natom)
     145           26 :       CALL reallocate(atom_info%atm_charge, 1, natom)
     146           26 :       CALL reallocate(atom_info%occup, 1, natom)
     147           26 :       CALL reallocate(atom_info%beta, 1, natom)
     148           26 :       CALL reallocate(atom_info%id_element, 1, natom)
     149              : 
     150              :       ! Element is assigned on the basis of the atm_name
     151           26 :       topology%aa_element = .TRUE.
     152              : 
     153              :       ! Coordinates
     154           26 :       CALL parser_get_next_line(parser, 1, at_end=my_end)
     155        38826 :       DO j = 1, natom - MOD(natom, 2), 2
     156        38800 :          IF (my_end) EXIT
     157        38800 :          READ (parser%input_line, *) atom_info%r(1, j), atom_info%r(2, j), atom_info%r(3, j), &
     158        77600 :             atom_info%r(1, j + 1), atom_info%r(2, j + 1), atom_info%r(3, j + 1)
     159              :          ! All these information will have to be setup elsewhere..
     160              :          ! CRD file does not contain anything related..
     161        38800 :          atom_info%id_atmname(j) = str2id(s2s("__UNDEF__"))
     162        38800 :          atom_info%id_molname(j) = str2id(s2s("__UNDEF__"))
     163        38800 :          atom_info%id_resname(j) = str2id(s2s("__UNDEF__"))
     164        38800 :          atom_info%id_element(j) = str2id(s2s("__UNDEF__"))
     165        38800 :          atom_info%resid(j) = HUGE(0)
     166        38800 :          atom_info%atm_mass(j) = HUGE(0.0_dp)
     167        38800 :          atom_info%atm_charge(j) = -HUGE(0.0_dp)
     168        38800 :          atom_info%r(1, j) = cp_unit_to_cp2k(atom_info%r(1, j), "angstrom")
     169        38800 :          atom_info%r(2, j) = cp_unit_to_cp2k(atom_info%r(2, j), "angstrom")
     170        38800 :          atom_info%r(3, j) = cp_unit_to_cp2k(atom_info%r(3, j), "angstrom")
     171              : 
     172        38800 :          atom_info%id_atmname(j + 1) = str2id(s2s("__UNDEF__"))
     173        38800 :          atom_info%id_molname(j + 1) = str2id(s2s("__UNDEF__"))
     174        38800 :          atom_info%id_resname(j + 1) = str2id(s2s("__UNDEF__"))
     175        38800 :          atom_info%id_element(j + 1) = str2id(s2s("__UNDEF__"))
     176        38800 :          atom_info%resid(j + 1) = HUGE(0)
     177        38800 :          atom_info%atm_mass(j + 1) = HUGE(0.0_dp)
     178        38800 :          atom_info%atm_charge(j + 1) = -HUGE(0.0_dp)
     179        38800 :          atom_info%r(1, j + 1) = cp_unit_to_cp2k(atom_info%r(1, j + 1), "angstrom")
     180        38800 :          atom_info%r(2, j + 1) = cp_unit_to_cp2k(atom_info%r(2, j + 1), "angstrom")
     181        38800 :          atom_info%r(3, j + 1) = cp_unit_to_cp2k(atom_info%r(3, j + 1), "angstrom")
     182              : 
     183        38826 :          CALL parser_get_next_line(parser, 1, at_end=my_end)
     184              :       END DO
     185              :       ! Trigger error
     186           26 :       IF ((my_end) .AND. (j /= natom - MOD(natom, 2) + 1)) THEN
     187            0 :          IF (j /= natom) THEN
     188            0 :             CPABORT("Error while reading CRD file. Unexpected end of file.")
     189              :          END IF
     190           26 :       ELSE IF (MOD(natom, 2) /= 0) THEN
     191              :          ! In case let's handle the last atom
     192            2 :          j = natom
     193            2 :          READ (parser%input_line, *) atom_info%r(1, j), atom_info%r(2, j), atom_info%r(3, j)
     194              :          ! All these information will have to be setup elsewhere..
     195              :          ! CRD file does not contain anything related..
     196            2 :          atom_info%id_atmname(j) = str2id(s2s("__UNDEF__"))
     197            2 :          atom_info%id_molname(j) = str2id(s2s("__UNDEF__"))
     198            2 :          atom_info%id_resname(j) = str2id(s2s("__UNDEF__"))
     199            2 :          atom_info%id_element(j) = str2id(s2s("__UNDEF__"))
     200            2 :          atom_info%resid(j) = HUGE(0)
     201            2 :          atom_info%atm_mass(j) = HUGE(0.0_dp)
     202            2 :          atom_info%atm_charge(j) = -HUGE(0.0_dp)
     203            2 :          atom_info%r(1, j) = cp_unit_to_cp2k(atom_info%r(1, j), "angstrom")
     204            2 :          atom_info%r(2, j) = cp_unit_to_cp2k(atom_info%r(2, j), "angstrom")
     205            2 :          atom_info%r(3, j) = cp_unit_to_cp2k(atom_info%r(3, j), "angstrom")
     206              : 
     207            2 :          CALL parser_get_next_line(parser, 1, at_end=my_end)
     208              :       END IF
     209              : 
     210           26 :       IF (my_end) THEN
     211           20 :          CPWARN_IF(j /= natom, "No VELOCITY or BOX information found in CRD file.")
     212              :       ELSE
     213              :          ! Velocities
     214            6 :          CALL reallocate(velocity, 1, 3, 1, natom)
     215        38604 :          DO j = 1, natom - MOD(natom, 2), 2
     216        38598 :             IF (my_end) EXIT
     217        38598 :             READ (parser%input_line, *) velocity(1, j), velocity(2, j), velocity(3, j), &
     218        77196 :                velocity(1, j + 1), velocity(2, j + 1), velocity(3, j + 1)
     219              : 
     220        38598 :             velocity(1, j) = cp_unit_to_cp2k(velocity(1, j), "angstrom*ps^-1")
     221        38598 :             velocity(2, j) = cp_unit_to_cp2k(velocity(2, j), "angstrom*ps^-1")
     222        38598 :             velocity(3, j) = cp_unit_to_cp2k(velocity(3, j), "angstrom*ps^-1")
     223       154392 :             velocity(1:3, j) = velocity(1:3, j)*amber_conv_factor
     224              : 
     225        38598 :             velocity(1, j + 1) = cp_unit_to_cp2k(velocity(1, j + 1), "angstrom*ps^-1")
     226        38598 :             velocity(2, j + 1) = cp_unit_to_cp2k(velocity(2, j + 1), "angstrom*ps^-1")
     227        38598 :             velocity(3, j + 1) = cp_unit_to_cp2k(velocity(3, j + 1), "angstrom*ps^-1")
     228       154392 :             velocity(1:3, j + 1) = velocity(1:3, j + 1)*amber_conv_factor
     229              : 
     230        38604 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
     231              :          END DO
     232            6 :          setup_velocities = .TRUE.
     233            6 :          IF ((my_end) .AND. (j /= natom - MOD(natom, 2) + 1)) THEN
     234            0 :             IF (j /= natom) THEN
     235              :                CALL cp_warn(__LOCATION__, &
     236              :                             "No VELOCITY information found in CRD file. Ignoring BOX information. "// &
     237            0 :                             "Please provide the BOX information directly from the main CP2K input! ")
     238              :             END IF
     239              :             setup_velocities = .FALSE.
     240            6 :          ELSE IF (MOD(natom, 2) /= 0) THEN
     241              :             ! In case let's handle the last atom
     242            0 :             j = natom
     243            0 :             READ (parser%input_line, *) velocity(1, j), velocity(2, j), velocity(3, j)
     244              : 
     245            0 :             velocity(1, j) = cp_unit_to_cp2k(velocity(1, j), "angstrom*ps^-1")
     246            0 :             velocity(2, j) = cp_unit_to_cp2k(velocity(2, j), "angstrom*ps^-1")
     247            0 :             velocity(3, j) = cp_unit_to_cp2k(velocity(3, j), "angstrom*ps^-1")
     248            0 :             velocity(1:3, j) = velocity(1:3, j)*amber_conv_factor
     249              : 
     250            0 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
     251              :          END IF
     252              :          IF (setup_velocities) THEN
     253            6 :             velocity_section => section_vals_get_subs_vals(subsys_section, "VELOCITY")
     254              :             CALL section_velocity_val_set(velocity_section, velocity=velocity, &
     255            6 :                                           conv_factor=1.0_dp)
     256              :          END IF
     257            6 :          DEALLOCATE (velocity)
     258              :       END IF
     259           26 :       IF (my_end) THEN
     260           20 :          CPWARN_IF(j /= natom, "BOX information missing in CRD file.")
     261              :       ELSE
     262            6 :          IF (j /= natom) THEN
     263              :             CALL cp_warn(__LOCATION__, &
     264              :                          "BOX information found in CRD file. They will be ignored. "// &
     265            6 :                          "Please provide the BOX information directly from the main CP2K input!")
     266              :          END IF
     267              :       END IF
     268           26 :       CALL parser_release(parser)
     269              :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
     270           26 :                                         "PRINT%TOPOLOGY_INFO/CRD_INFO")
     271           26 :       CALL timestop(handle)
     272              : 
     273           78 :    END SUBROUTINE read_coordinate_crd
     274              : 
     275              : ! **************************************************************************************************
     276              : !> \brief Read AMBER topology file (.top) : At this level we parse only the
     277              : !>        connectivity info the .top file. ForceField information will be
     278              : !>        handled later
     279              : !>
     280              : !> \param filename ...
     281              : !> \param topology ...
     282              : !> \param para_env ...
     283              : !> \param subsys_section ...
     284              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
     285              : ! **************************************************************************************************
     286           24 :    SUBROUTINE read_connectivity_amber(filename, topology, para_env, subsys_section)
     287              :       CHARACTER(LEN=*), INTENT(IN)                       :: filename
     288              :       TYPE(topology_parameters_type), INTENT(INOUT)      :: topology
     289              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     290              :       TYPE(section_vals_type), POINTER                   :: subsys_section
     291              : 
     292              :       CHARACTER(len=*), PARAMETER :: routineN = 'read_connectivity_amber'
     293              : 
     294              :       INTEGER                                            :: handle, iw
     295              :       TYPE(atom_info_type), POINTER                      :: atom_info
     296              :       TYPE(connectivity_info_type), POINTER              :: conn_info
     297              :       TYPE(cp_logger_type), POINTER                      :: logger
     298              : 
     299           24 :       NULLIFY (logger)
     300           24 :       CALL timeset(routineN, handle)
     301           24 :       logger => cp_get_default_logger()
     302              :       iw = cp_print_key_unit_nr(logger, subsys_section, "PRINT%TOPOLOGY_INFO/AMBER_INFO", &
     303           24 :                                 extension=".subsysLog")
     304              : 
     305           24 :       atom_info => topology%atom_info
     306           24 :       conn_info => topology%conn_info
     307              : 
     308              :       ! Read the Amber topology file
     309              :       CALL rdparm_amber_8(filename, iw, para_env, do_connectivity=.TRUE., do_forcefield=.FALSE., &
     310           24 :                           atom_info=atom_info, conn_info=conn_info)
     311              : 
     312              :       ! Molnames have been internally generated
     313           24 :       topology%molname_generated = .TRUE.
     314              : 
     315              :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
     316           24 :                                         "PRINT%TOPOLOGY_INFO/AMBER_INFO")
     317           24 :       CALL timestop(handle)
     318           24 :    END SUBROUTINE read_connectivity_amber
     319              : 
     320              : ! **************************************************************************************************
     321              : !> \brief  Access information form the AMBER topology file
     322              : !>         Notes on file structure:
     323              : !>
     324              : !>          NATOM        ! Total number of Atoms
     325              : !>          NTYPES       ! Total number of distinct atom types
     326              : !>          NBONH        ! Number of bonds containing hydrogens
     327              : !>          MBONA        ! Number of bonds not containing hydrogens
     328              : !>          NTHETH       ! Number of angles containing hydrogens
     329              : !>          MTHETA       ! Number of angles not containing hydrogens
     330              : !>          NPHIH        ! Number of dihedrals containing hydrogens
     331              : !>          MPHIA        ! Number of dihedrals not containing hydrogens
     332              : !>          NHPARM       !    currently NOT USED
     333              : !>          NPARM        !    set to 1 if LES is used
     334              : !>          NNB          !    number of excluded atoms
     335              : !>          NRES         ! Number of residues
     336              : !>          NBONA        !    MBONA  + number of constraint bonds     ( in v.8 NBONA=MBONA)
     337              : !>          NTHETA       !    MTHETA + number of constraint angles    ( in v.8 NBONA=MBONA)
     338              : !>          NPHIA        !    MPHIA  + number of constraint dihedrals ( in v.8 NBONA=MBONA)
     339              : !>          NUMBND       ! Number of unique bond types
     340              : !>          NUMANG       ! Number of unique angle types
     341              : !>          NPTRA        ! Number of unique dihedral types
     342              : !>          NATYP        ! Number of atom types in parameter file
     343              : !>          NPHB         ! Number of distinct 10-12 hydrogen bond pair types
     344              : !>          IFPERT       !    Variable not used in this converter...
     345              : !>          NBPER        !    Variable not used in this converter...
     346              : !>          NGPER        !    Variable not used in this converter...
     347              : !>          NDPER        !    Variable not used in this converter...
     348              : !>          MBPER        !    Variable not used in this converter...
     349              : !>          MGPER        !    Variable not used in this converter...
     350              : !>          MDPER        !    Variable not used in this converter...
     351              : !>          IFBOX        !    Variable not used in this converter...
     352              : !>          NMXRS        !    Variable not used in this converter...
     353              : !>          IFCAP        !    Variable not used in this converter...
     354              : !>          NUMEXTRA     !    Variable not used in this converter...
     355              : !>
     356              : !> \param filename ...
     357              : !> \param output_unit ...
     358              : !> \param para_env ...
     359              : !> \param do_connectivity ...
     360              : !> \param do_forcefield ...
     361              : !> \param atom_info ...
     362              : !> \param conn_info ...
     363              : !> \param amb_info ...
     364              : !> \param particle_set ...
     365              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
     366              : ! **************************************************************************************************
     367           40 :    SUBROUTINE rdparm_amber_8(filename, output_unit, para_env, do_connectivity, &
     368              :                              do_forcefield, atom_info, conn_info, amb_info, particle_set)
     369              : 
     370              :       CHARACTER(LEN=*), INTENT(IN)                       :: filename
     371              :       INTEGER, INTENT(IN)                                :: output_unit
     372              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     373              :       LOGICAL, INTENT(IN)                                :: do_connectivity, do_forcefield
     374              :       TYPE(atom_info_type), OPTIONAL, POINTER            :: atom_info
     375              :       TYPE(connectivity_info_type), OPTIONAL, POINTER    :: conn_info
     376              :       TYPE(amber_info_type), OPTIONAL, POINTER           :: amb_info
     377              :       TYPE(particle_type), DIMENSION(:), OPTIONAL, &
     378              :          POINTER                                         :: particle_set
     379              : 
     380              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'rdparm_amber_8'
     381              : 
     382              :       CHARACTER(LEN=default_string_length)               :: input_format, section
     383              :       CHARACTER(LEN=default_string_length), &
     384           80 :          ALLOCATABLE, DIMENSION(:)                       :: isymbl, labres, raw_isymbl, strtmp_a
     385              :       INTEGER :: handle, handle2, i, ifbox, ifcap, ifpert, index_now, info(31), istart, mbona, &
     386              :          mbper, mdper, mgper, mphia, mtheta, natom, natom_prev, natyp, nbona, nbond_prev, nbonh, &
     387              :          nbper, ndper, ngper, nhparm, nmxrs, nnb, nparm, nphb, nphi_prev, nphia, nphih, nptra, &
     388              :          nres, nsize, ntheta, ntheta_prev, ntheth, ntypes, numang, numbnd, numextra, &
     389              :          unique_torsions
     390           40 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: iac, ib, ibh, icb, icbh, ico, icp, icph, &
     391           40 :                                                             ict, icth, ip, iph, ipres, it, ith, &
     392           40 :                                                             iwork, jb, jbh, jp, jph, jt, jth, kp, &
     393           40 :                                                             kph, kt, kth, lp, lph
     394           40 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: full_torsions
     395              :       LOGICAL                                            :: check, valid_format
     396           80 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: asol, bsol, cn1, cn2, phase, pk, pn, &
     397           40 :                                                             req, rk, teq, tk
     398              :       TYPE(cp_parser_type)                               :: parser
     399              : 
     400           40 :       CALL timeset(routineN, handle)
     401           40 :       IF (output_unit > 0) WRITE (output_unit, '(/,A)') " AMBER_INFO| Reading Amber Topology File: "// &
     402            3 :          TRIM(filename)
     403           40 :       CALL parser_create(parser, filename, para_env=para_env, parse_white_lines=.TRUE.)
     404           40 :       valid_format = check_amber_8_std(parser, output_unit)
     405           40 :       IF (valid_format) THEN
     406         1560 :          DO WHILE (get_section_parmtop(parser, section, input_format))
     407           40 :             SELECT CASE (TRIM(section))
     408              :             CASE ("TITLE")
     409              :                ! Who cares about the title?
     410           40 :                CYCLE
     411              :             CASE ("POINTERS")
     412           40 :                CALL rd_amber_section(parser, section, info, 31)
     413              :                ! Assign pointers to the corresponding labels
     414              :                ! just for convenience to have something more human readable
     415           40 :                natom = info(1)
     416           40 :                ntypes = info(2)
     417           40 :                nbonh = info(3)
     418           40 :                mbona = info(4)
     419           40 :                ntheth = info(5)
     420           40 :                mtheta = info(6)
     421           40 :                nphih = info(7)
     422           40 :                mphia = info(8)
     423           40 :                nhparm = info(9)
     424           40 :                nparm = info(10)
     425           40 :                nnb = info(11)
     426           40 :                nres = info(12)
     427           40 :                nbona = info(13)
     428           40 :                ntheta = info(14)
     429           40 :                nphia = info(15)
     430           40 :                numbnd = info(16)
     431           40 :                numang = info(17)
     432           40 :                nptra = info(18)
     433           40 :                natyp = info(19)
     434           40 :                nphb = info(20)
     435           40 :                ifpert = info(21)
     436           40 :                nbper = info(22)
     437           40 :                ngper = info(23)
     438           40 :                ndper = info(24)
     439           40 :                mbper = info(25)
     440           40 :                mgper = info(26)
     441           40 :                mdper = info(27)
     442           40 :                ifbox = info(28)
     443           40 :                nmxrs = info(29)
     444           40 :                ifcap = info(30)
     445           40 :                numextra = info(31)
     446              : 
     447              :                ! Print some info if requested
     448           40 :                IF (output_unit > 0) THEN
     449            3 :                   WRITE (output_unit, '(A,/)') " AMBER_INFO| Information from AMBER topology file:"
     450              :                   WRITE (output_unit, 1000) &
     451            3 :                      natom, ntypes, nbonh, mbona, ntheth, mtheta, nphih, &
     452            3 :                      mphia, nhparm, nparm, nnb, nres, nbona, ntheta, &
     453            3 :                      nphia, numbnd, numang, nptra, natyp, nphb, ifbox, &
     454            6 :                      nmxrs, ifcap, numextra
     455              :                END IF
     456              : 
     457              :                ! Allocate temporary arrays
     458           40 :                IF (do_connectivity) THEN
     459           24 :                   check = PRESENT(atom_info) .AND. PRESENT(conn_info)
     460           24 :                   CPASSERT(check)
     461           24 :                   natom_prev = 0
     462           24 :                   IF (ASSOCIATED(atom_info%id_molname)) natom_prev = SIZE(atom_info%id_molname)
     463              :                   ! Allocate for extracting connectivity infos
     464           72 :                   ALLOCATE (labres(nres))
     465           72 :                   ALLOCATE (ipres(nres))
     466              :                END IF
     467           40 :                IF (do_forcefield) THEN
     468              :                   ! Allocate for extracting forcefield infos
     469           48 :                   ALLOCATE (iac(natom))
     470           48 :                   ALLOCATE (ico(ntypes*ntypes))
     471           48 :                   ALLOCATE (rk(numbnd))
     472           32 :                   ALLOCATE (req(numbnd))
     473           48 :                   ALLOCATE (tk(numang))
     474           32 :                   ALLOCATE (teq(numang))
     475           46 :                   ALLOCATE (pk(nptra))
     476           30 :                   ALLOCATE (pn(nptra))
     477           30 :                   ALLOCATE (phase(nptra))
     478           48 :                   ALLOCATE (cn1(ntypes*(ntypes + 1)/2))
     479           32 :                   ALLOCATE (cn2(ntypes*(ntypes + 1)/2))
     480           32 :                   ALLOCATE (asol(ntypes*(ntypes + 1)/2))
     481           32 :                   ALLOCATE (bsol(ntypes*(ntypes + 1)/2))
     482              :                END IF
     483              :                ! Always Allocate
     484          120 :                ALLOCATE (ibh(nbonh))
     485           80 :                ALLOCATE (jbh(nbonh))
     486           80 :                ALLOCATE (icbh(nbonh))
     487          116 :                ALLOCATE (ib(nbona))
     488           76 :                ALLOCATE (jb(nbona))
     489           76 :                ALLOCATE (icb(nbona))
     490          120 :                ALLOCATE (ith(ntheth))
     491           80 :                ALLOCATE (jth(ntheth))
     492           80 :                ALLOCATE (kth(ntheth))
     493           80 :                ALLOCATE (icth(ntheth))
     494          116 :                ALLOCATE (it(ntheta))
     495           76 :                ALLOCATE (jt(ntheta))
     496           76 :                ALLOCATE (kt(ntheta))
     497           76 :                ALLOCATE (ict(ntheta))
     498          116 :                ALLOCATE (iph(nphih))
     499           76 :                ALLOCATE (jph(nphih))
     500           76 :                ALLOCATE (kph(nphih))
     501           76 :                ALLOCATE (lph(nphih))
     502           76 :                ALLOCATE (icph(nphih))
     503          116 :                ALLOCATE (ip(nphia))
     504           76 :                ALLOCATE (jp(nphia))
     505           76 :                ALLOCATE (kp(nphia))
     506           76 :                ALLOCATE (lp(nphia))
     507           76 :                ALLOCATE (icp(nphia))
     508              :             CASE ("ATOM_NAME")
     509              :                ! Atom names are just ignored according the CP2K philosophy
     510           40 :                CYCLE
     511              :             CASE ("AMBER_ATOM_TYPE")
     512           40 :                IF (.NOT. do_connectivity) CYCLE
     513           24 :                CALL reallocate(atom_info%id_atmname, 1, natom_prev + natom)
     514           72 :                ALLOCATE (strtmp_a(natom))
     515           24 :                CALL rd_amber_section(parser, section, strtmp_a, natom)
     516        78896 :                DO i = 1, natom
     517        78896 :                   atom_info%id_atmname(natom_prev + i) = str2id(strtmp_a(i))
     518              :                END DO
     519           24 :                DEALLOCATE (strtmp_a)
     520              :             CASE ("CHARGE")
     521           40 :                IF (.NOT. do_connectivity) CYCLE
     522           24 :                CALL reallocate(atom_info%atm_charge, 1, natom_prev + natom)
     523           24 :                CALL rd_amber_section(parser, section, atom_info%atm_charge(natom_prev + 1:), natom)
     524              :                ! Convert charges into atomic units
     525        78896 :                atom_info%atm_charge(natom_prev + 1:) = atom_info%atm_charge(natom_prev + 1:)/amber_conv_charge
     526              :             CASE ("MASS")
     527           40 :                IF (.NOT. do_connectivity) CYCLE
     528           24 :                CALL reallocate(atom_info%atm_mass, 1, natom_prev + natom)
     529           24 :                CALL rd_amber_section(parser, section, atom_info%atm_mass(natom_prev + 1:), natom)
     530              :             CASE ("RESIDUE_LABEL")
     531           40 :                IF (.NOT. do_connectivity) CYCLE
     532           24 :                CALL reallocate(atom_info%id_resname, 1, natom_prev + natom)
     533           24 :                CALL rd_amber_section(parser, section, labres, nres)
     534              :             CASE ("RESIDUE_POINTER")
     535           40 :                IF (.NOT. do_connectivity) CYCLE
     536           24 :                CALL reallocate(atom_info%resid, 1, natom_prev + natom)
     537           24 :                CALL rd_amber_section(parser, section, ipres, nres)
     538              :             CASE ("ATOM_TYPE_INDEX")
     539           40 :                IF (.NOT. do_forcefield) CYCLE
     540           16 :                CALL rd_amber_section(parser, section, iac, natom)
     541              :             CASE ("NONBONDED_PARM_INDEX")
     542           40 :                IF (.NOT. do_forcefield) CYCLE
     543           16 :                CALL rd_amber_section(parser, section, ico, ntypes**2)
     544              :             CASE ("BOND_FORCE_CONSTANT")
     545           40 :                IF (.NOT. do_forcefield) CYCLE
     546           16 :                CALL rd_amber_section(parser, section, rk, numbnd)
     547              :             CASE ("BOND_EQUIL_VALUE")
     548           40 :                IF (.NOT. do_forcefield) CYCLE
     549           16 :                CALL rd_amber_section(parser, section, req, numbnd)
     550              :             CASE ("ANGLE_FORCE_CONSTANT")
     551           40 :                IF (.NOT. do_forcefield) CYCLE
     552           16 :                CALL rd_amber_section(parser, section, tk, numang)
     553              :             CASE ("ANGLE_EQUIL_VALUE")
     554           40 :                IF (.NOT. do_forcefield) CYCLE
     555           16 :                CALL rd_amber_section(parser, section, teq, numang)
     556              :             CASE ("DIHEDRAL_FORCE_CONSTANT")
     557           40 :                IF (.NOT. do_forcefield) CYCLE
     558           16 :                CALL rd_amber_section(parser, section, pk, nptra)
     559           16 :                IF (nptra <= 0) CYCLE
     560              :                ! Save raw values
     561           14 :                IF (ASSOCIATED(amb_info%raw_torsion_k)) DEALLOCATE (amb_info%raw_torsion_k)
     562          380 :                ALLOCATE (amb_info%raw_torsion_k(nptra), source=pk)
     563              :             CASE ("DIHEDRAL_PERIODICITY")
     564           40 :                IF (.NOT. do_forcefield) CYCLE
     565           16 :                CALL rd_amber_section(parser, section, pn, nptra)
     566           16 :                IF (nptra <= 0) CYCLE
     567              :                ! Save raw values
     568           14 :                IF (ASSOCIATED(amb_info%raw_torsion_m)) DEALLOCATE (amb_info%raw_torsion_m)
     569          380 :                ALLOCATE (amb_info%raw_torsion_m(nptra), source=pn)
     570              :             CASE ("DIHEDRAL_PHASE")
     571           40 :                IF (.NOT. do_forcefield) CYCLE
     572           16 :                CALL rd_amber_section(parser, section, phase, nptra)
     573           16 :                IF (nptra <= 0) CYCLE
     574              :                ! Save raw values
     575           14 :                IF (ASSOCIATED(amb_info%raw_torsion_phi0)) DEALLOCATE (amb_info%raw_torsion_phi0)
     576          380 :                ALLOCATE (amb_info%raw_torsion_phi0(nptra), source=phase)
     577              :             CASE ("LENNARD_JONES_ACOEF")
     578           40 :                IF (.NOT. do_forcefield) CYCLE
     579           16 :                CALL rd_amber_section(parser, section, cn1, ntypes*(ntypes + 1)/2)
     580              :             CASE ("LENNARD_JONES_BCOEF")
     581           40 :                IF (.NOT. do_forcefield) CYCLE
     582           16 :                CALL rd_amber_section(parser, section, cn2, ntypes*(ntypes + 1)/2)
     583              :             CASE ("HBOND_ACOEF")
     584           40 :                IF (.NOT. do_forcefield) CYCLE
     585           16 :                CALL rd_amber_section(parser, section, asol, nphb)
     586              :             CASE ("HBOND_BCOEF")
     587           40 :                IF (.NOT. do_forcefield) CYCLE
     588           16 :                CALL rd_amber_section(parser, section, bsol, nphb)
     589              :             CASE ("BONDS_INC_HYDROGEN")
     590              :                ! We always need to parse this information both for connectivity and forcefields
     591           40 :                CALL rd_amber_section(parser, section, ibh, jbh, icbh, nbonh)
     592              :                ! Conver to an atomic index
     593       100064 :                ibh(:) = ibh(:)/3 + 1
     594       100064 :                jbh(:) = jbh(:)/3 + 1
     595              :             CASE ("BONDS_WITHOUT_HYDROGEN")
     596              :                ! We always need to parse this information both for connectivity and forcefields
     597           40 :                CALL rd_amber_section(parser, section, ib, jb, icb, nbona)
     598              :                ! Conver to an atomic index
     599        14058 :                ib(:) = ib(:)/3 + 1
     600        14058 :                jb(:) = jb(:)/3 + 1
     601              :             CASE ("ANGLES_INC_HYDROGEN")
     602              :                ! We always need to parse this information both for connectivity and forcefields
     603           40 :                CALL rd_amber_section(parser, section, ith, jth, kth, icth, ntheth)
     604              :                ! Conver to an atomic index
     605        72562 :                ith(:) = ith(:)/3 + 1
     606        72562 :                jth(:) = jth(:)/3 + 1
     607        72562 :                kth(:) = kth(:)/3 + 1
     608              :             CASE ("ANGLES_WITHOUT_HYDROGEN")
     609              :                ! We always need to parse this information both for connectivity and forcefields
     610           40 :                CALL rd_amber_section(parser, section, it, jt, kt, ict, ntheta)
     611              :                ! Conver to an atomic index
     612        18994 :                it(:) = it(:)/3 + 1
     613        18994 :                jt(:) = jt(:)/3 + 1
     614        18994 :                kt(:) = kt(:)/3 + 1
     615              :             CASE ("DIHEDRALS_INC_HYDROGEN")
     616              :                ! We always need to parse this information both for connectivity and forcefields
     617           40 :                CALL rd_amber_section(parser, section, iph, jph, kph, lph, icph, nphih)
     618              :                ! Conver to an atomic index
     619        56688 :                iph(:) = iph(:)/3 + 1
     620        56688 :                jph(:) = jph(:)/3 + 1
     621        56688 :                kph(:) = ABS(kph(:))/3 + 1
     622        56688 :                lph(:) = ABS(lph(:))/3 + 1
     623              :             CASE ("DIHEDRALS_WITHOUT_HYDROGEN")
     624              :                ! We always need to parse this information both for connectivity and forcefields
     625           40 :                CALL rd_amber_section(parser, section, ip, jp, kp, lp, icp, nphia)
     626              :                ! Conver to an atomic index
     627        45316 :                ip(:) = ip(:)/3 + 1
     628        45316 :                jp(:) = jp(:)/3 + 1
     629        45316 :                kp(:) = ABS(kp(:))/3 + 1
     630        46852 :                lp(:) = ABS(lp(:))/3 + 1
     631              :             CASE DEFAULT
     632              :                ! Just Ignore other sections...
     633              :             END SELECT
     634              :          END DO
     635              :          ! Save raw torsion info: atom indices and dihedral index
     636           40 :          IF (do_forcefield .AND. (nphih + nphia > 0)) THEN
     637           14 :             IF (ASSOCIATED(amb_info%raw_torsion_id)) DEALLOCATE (amb_info%raw_torsion_id)
     638           42 :             ALLOCATE (amb_info%raw_torsion_id(5, nphih + nphia))
     639        28132 :             DO i = 1, nphih
     640        28118 :                amb_info%raw_torsion_id(1, i) = iph(i)
     641        28118 :                amb_info%raw_torsion_id(2, i) = jph(i)
     642        28118 :                amb_info%raw_torsion_id(3, i) = kph(i)
     643        28118 :                amb_info%raw_torsion_id(4, i) = lph(i)
     644        28132 :                amb_info%raw_torsion_id(5, i) = icph(i)
     645              :             END DO
     646        22356 :             DO i = 1, nphia
     647        22342 :                amb_info%raw_torsion_id(1, nphih + i) = ip(i)
     648        22342 :                amb_info%raw_torsion_id(2, nphih + i) = jp(i)
     649        22342 :                amb_info%raw_torsion_id(3, nphih + i) = kp(i)
     650        22342 :                amb_info%raw_torsion_id(4, nphih + i) = lp(i)
     651        22356 :                amb_info%raw_torsion_id(5, nphih + i) = icp(i)
     652              :             END DO
     653              :          END IF
     654              :       END IF
     655              : 
     656              :       ! Extracts connectivity info from the AMBER topology file
     657           40 :       IF (do_connectivity) THEN
     658           24 :          CALL timeset(TRIM(routineN)//"_connectivity", handle2)
     659              :          ! ----------------------------------------------------------
     660              :          ! Conform Amber Names with CHARMM convention (kind<->charge)
     661              :          ! ----------------------------------------------------------
     662           72 :          ALLOCATE (isymbl(natom))
     663           72 :          ALLOCATE (iwork(natom))
     664              : 
     665        78896 :          DO i = 1, SIZE(isymbl)
     666        78896 :             isymbl(i) = id2str(atom_info%id_atmname(natom_prev + i))
     667              :          END DO
     668              : 
     669              :          ! Sort atom names + charges and identify unique types
     670           24 :          CALL sort(isymbl, natom, iwork)
     671           48 :          ALLOCATE (raw_isymbl(natom))
     672        78896 :          raw_isymbl(:) = isymbl
     673              : 
     674           24 :          istart = 1
     675        78872 :          DO i = 2, natom
     676        78872 :             IF (TRIM(isymbl(i)) /= TRIM(isymbl(istart))) THEN
     677          244 :                CALL conform_atom_type_low(isymbl, iwork, i, istart, atom_info%atm_charge(natom_prev + 1:))
     678          244 :                istart = i
     679              :             END IF
     680              :          END DO
     681           24 :          CALL conform_atom_type_low(isymbl, iwork, i, istart, atom_info%atm_charge(natom_prev + 1:))
     682              : 
     683           24 :          CALL resolve_atom_type_collisions(isymbl, raw_isymbl)
     684              : 
     685              :          ! Copy back the modified and conformed atom types
     686        78896 :          DO i = 1, natom
     687        78896 :             atom_info%id_atmname(natom_prev + iwork(i)) = str2id(s2s(isymbl(i)))
     688              :          END DO
     689              : 
     690              :          ! -----------------------------------------------------------
     691              :          ! Fill residue_name and residue_id information before exiting
     692              :          ! -----------------------------------------------------------
     693        22734 :          DO i = 1, nres - 1
     694       123798 :             atom_info%id_resname(natom_prev + ipres(i):natom_prev + ipres(i + 1)) = str2id(s2s(labres(i)))
     695       123822 :             atom_info%resid(natom_prev + ipres(i):natom_prev + ipres(i + 1)) = i
     696              :          END DO
     697          518 :          atom_info%id_resname(natom_prev + ipres(i):natom_prev + natom) = str2id(s2s(labres(i)))
     698          518 :          atom_info%resid(natom_prev + ipres(i):natom_prev + natom) = i
     699              : 
     700              :          ! Deallocate when extracting connectivity infos
     701           24 :          DEALLOCATE (iwork)
     702           24 :          DEALLOCATE (isymbl)
     703           24 :          DEALLOCATE (raw_isymbl)
     704           24 :          DEALLOCATE (labres)
     705           24 :          DEALLOCATE (ipres)
     706              : 
     707              :          ! ----------------------------------------------------------
     708              :          ! Copy connectivity
     709              :          ! ----------------------------------------------------------
     710              :          ! BONDS
     711           24 :          nbond_prev = 0
     712           24 :          IF (ASSOCIATED(conn_info%bond_a)) nbond_prev = SIZE(conn_info%bond_a)
     713              : 
     714           24 :          CALL reallocate(conn_info%bond_a, 1, nbond_prev + nbonh + nbona)
     715           24 :          CALL reallocate(conn_info%bond_b, 1, nbond_prev + nbonh + nbona)
     716        50096 :          DO i = 1, nbonh
     717        50072 :             index_now = nbond_prev + i
     718        50072 :             conn_info%bond_a(index_now) = natom_prev + ibh(i)
     719        50096 :             conn_info%bond_b(index_now) = natom_prev + jbh(i)
     720              :          END DO
     721         7162 :          DO i = 1, nbona
     722         7138 :             index_now = nbond_prev + i + nbonh
     723         7138 :             conn_info%bond_a(index_now) = natom_prev + ib(i)
     724         7162 :             conn_info%bond_b(index_now) = natom_prev + jb(i)
     725              :          END DO
     726              : 
     727              :          ! ANGLES
     728           24 :          ntheta_prev = 0
     729           24 :          IF (ASSOCIATED(conn_info%theta_a)) ntheta_prev = SIZE(conn_info%theta_a)
     730              : 
     731           24 :          CALL reallocate(conn_info%theta_a, 1, ntheta_prev + ntheth + ntheta)
     732           24 :          CALL reallocate(conn_info%theta_b, 1, ntheta_prev + ntheth + ntheta)
     733           24 :          CALL reallocate(conn_info%theta_c, 1, ntheta_prev + ntheth + ntheta)
     734        36406 :          DO i = 1, ntheth
     735        36382 :             index_now = ntheta_prev + i
     736        36382 :             conn_info%theta_a(index_now) = natom_prev + ith(i)
     737        36382 :             conn_info%theta_b(index_now) = natom_prev + jth(i)
     738        36406 :             conn_info%theta_c(index_now) = natom_prev + kth(i)
     739              :          END DO
     740         9692 :          DO i = 1, ntheta
     741         9668 :             index_now = ntheta_prev + i + ntheth
     742         9668 :             conn_info%theta_a(index_now) = natom_prev + it(i)
     743         9668 :             conn_info%theta_b(index_now) = natom_prev + jt(i)
     744         9692 :             conn_info%theta_c(index_now) = natom_prev + kt(i)
     745              :          END DO
     746              : 
     747              :          ! TORSIONS
     748              :          ! For torsions we need to find out the unique torsions
     749              :          ! defined in the amber parmtop
     750           24 :          nphi_prev = 0
     751           24 :          IF (ASSOCIATED(conn_info%phi_a)) nphi_prev = SIZE(conn_info%phi_a)
     752              : 
     753           24 :          CALL reallocate(conn_info%phi_a, 1, nphi_prev + nphih + nphia)
     754           24 :          CALL reallocate(conn_info%phi_b, 1, nphi_prev + nphih + nphia)
     755           24 :          CALL reallocate(conn_info%phi_c, 1, nphi_prev + nphih + nphia)
     756           24 :          CALL reallocate(conn_info%phi_d, 1, nphi_prev + nphih + nphia)
     757              : 
     758           24 :          IF (nphih + nphia /= 0) THEN
     759           66 :             ALLOCATE (full_torsions(4, nphih + nphia))
     760           66 :             ALLOCATE (iwork(nphih + nphia))
     761              : 
     762        28552 :             DO i = 1, nphih
     763        28530 :                full_torsions(1, i) = iph(i)
     764        28530 :                full_torsions(2, i) = jph(i)
     765        28530 :                full_torsions(3, i) = kph(i)
     766        28552 :                full_torsions(4, i) = lph(i)
     767              :             END DO
     768        22956 :             DO i = 1, nphia
     769        22934 :                full_torsions(1, nphih + i) = ip(i)
     770        22934 :                full_torsions(2, nphih + i) = jp(i)
     771        22934 :                full_torsions(3, nphih + i) = kp(i)
     772        22956 :                full_torsions(4, nphih + i) = lp(i)
     773              :             END DO
     774           22 :             CALL sort(full_torsions, 1, nphih + nphia, 1, 4, iwork)
     775              : 
     776           22 :             unique_torsions = nphi_prev + 1
     777           22 :             conn_info%phi_a(unique_torsions) = natom_prev + full_torsions(1, 1)
     778           22 :             conn_info%phi_b(unique_torsions) = natom_prev + full_torsions(2, 1)
     779           22 :             conn_info%phi_c(unique_torsions) = natom_prev + full_torsions(3, 1)
     780           22 :             conn_info%phi_d(unique_torsions) = natom_prev + full_torsions(4, 1)
     781        51464 :             DO i = 2, nphih + nphia
     782              :                IF ((full_torsions(1, i) /= full_torsions(1, i - 1)) .OR. &
     783              :                    (full_torsions(2, i) /= full_torsions(2, i - 1)) .OR. &
     784        51442 :                    (full_torsions(3, i) /= full_torsions(3, i - 1)) .OR. &
     785           22 :                    (full_torsions(4, i) /= full_torsions(4, i - 1))) THEN
     786        37652 :                   unique_torsions = unique_torsions + 1
     787        37652 :                   conn_info%phi_a(unique_torsions) = natom_prev + full_torsions(1, i)
     788        37652 :                   conn_info%phi_b(unique_torsions) = natom_prev + full_torsions(2, i)
     789        37652 :                   conn_info%phi_c(unique_torsions) = natom_prev + full_torsions(3, i)
     790        37652 :                   conn_info%phi_d(unique_torsions) = natom_prev + full_torsions(4, i)
     791              :                END IF
     792              :             END DO
     793           22 :             CALL reallocate(conn_info%phi_a, 1, unique_torsions)
     794           22 :             CALL reallocate(conn_info%phi_b, 1, unique_torsions)
     795           22 :             CALL reallocate(conn_info%phi_c, 1, unique_torsions)
     796           22 :             CALL reallocate(conn_info%phi_d, 1, unique_torsions)
     797              : 
     798           22 :             DEALLOCATE (full_torsions)
     799           22 :             DEALLOCATE (iwork)
     800              :          END IF
     801              :          ! IMPROPERS
     802           24 :          CALL reallocate(conn_info%impr_a, 1, 0)
     803           24 :          CALL reallocate(conn_info%impr_b, 1, 0)
     804           24 :          CALL reallocate(conn_info%impr_c, 1, 0)
     805           24 :          CALL reallocate(conn_info%impr_d, 1, 0)
     806              : 
     807              :          ! ----------------------------------------------------------
     808              :          ! Generate molecule names
     809              :          ! ----------------------------------------------------------
     810           24 :          CALL reallocate(atom_info%id_molname, 1, natom_prev + natom)
     811        78896 :          atom_info%id_molname(natom_prev + 1:natom_prev + natom) = str2id(s2s("__UNDEF__"))
     812              :          CALL topology_generate_molname(conn_info, natom, natom_prev, nbond_prev, &
     813           24 :                                         atom_info%id_molname(natom_prev + 1:natom_prev + natom))
     814           48 :          CALL timestop(handle2)
     815              :       END IF
     816              : 
     817              :       ! Extracts force fields info from the AMBER topology file
     818           40 :       IF (do_forcefield) THEN
     819           16 :          CALL timeset(TRIM(routineN)//"_forcefield", handle2)
     820              :          ! ----------------------------------------------------------
     821              :          ! Force Fields informations related to bonds
     822              :          ! ----------------------------------------------------------
     823           16 :          CALL reallocate(amb_info%bond_a, 1, buffer_size)
     824           16 :          CALL reallocate(amb_info%bond_b, 1, buffer_size)
     825           16 :          CALL reallocate(amb_info%bond_k, 1, buffer_size)
     826           16 :          CALL reallocate(amb_info%bond_r0, 1, buffer_size)
     827           16 :          nsize = 0
     828              :          ! Bonds containing hydrogens
     829              :          CALL post_process_bonds_info(amb_info%bond_a, amb_info%bond_b, &
     830              :                                       amb_info%bond_k, amb_info%bond_r0, particle_set, nsize, &
     831           16 :                                       nbonh, ibh, jbh, icbh, rk, req)
     832              :          ! Bonds non-containing hydrogens
     833              :          CALL post_process_bonds_info(amb_info%bond_a, amb_info%bond_b, &
     834              :                                       amb_info%bond_k, amb_info%bond_r0, particle_set, nsize, &
     835           16 :                                       nbona, ib, jb, icb, rk, req)
     836              :          ! Shrink arrays size to the minimal request
     837           16 :          CALL reallocate(amb_info%bond_a, 1, nsize)
     838           16 :          CALL reallocate(amb_info%bond_b, 1, nsize)
     839           16 :          CALL reallocate(amb_info%bond_k, 1, nsize)
     840           16 :          CALL reallocate(amb_info%bond_r0, 1, nsize)
     841              : 
     842              :          ! ----------------------------------------------------------
     843              :          ! Force Fields informations related to bends
     844              :          ! ----------------------------------------------------------
     845           16 :          CALL reallocate(amb_info%bend_a, 1, buffer_size)
     846           16 :          CALL reallocate(amb_info%bend_b, 1, buffer_size)
     847           16 :          CALL reallocate(amb_info%bend_c, 1, buffer_size)
     848           16 :          CALL reallocate(amb_info%bend_k, 1, buffer_size)
     849           16 :          CALL reallocate(amb_info%bend_theta0, 1, buffer_size)
     850           16 :          nsize = 0
     851              :          ! Bends containing hydrogens
     852              :          CALL post_process_bends_info(amb_info%bend_a, amb_info%bend_b, &
     853              :                                       amb_info%bend_c, amb_info%bend_k, amb_info%bend_theta0, &
     854           16 :                                       particle_set, nsize, ntheth, ith, jth, kth, icth, tk, teq)
     855              :          ! Bends non-containing hydrogens
     856              :          CALL post_process_bends_info(amb_info%bend_a, amb_info%bend_b, &
     857              :                                       amb_info%bend_c, amb_info%bend_k, amb_info%bend_theta0, &
     858           16 :                                       particle_set, nsize, ntheta, it, jt, kt, ict, tk, teq)
     859              :          ! Shrink arrays size to the minimal request
     860           16 :          CALL reallocate(amb_info%bend_a, 1, nsize)
     861           16 :          CALL reallocate(amb_info%bend_b, 1, nsize)
     862           16 :          CALL reallocate(amb_info%bend_c, 1, nsize)
     863           16 :          CALL reallocate(amb_info%bend_k, 1, nsize)
     864           16 :          CALL reallocate(amb_info%bend_theta0, 1, nsize)
     865              : 
     866              :          ! ----------------------------------------------------------
     867              :          ! Force Fields informations related to torsions
     868              :          ! in amb_info%phi0 we store PHI0
     869              :          ! ----------------------------------------------------------
     870              : 
     871           16 :          CALL reallocate(amb_info%torsion_a, 1, buffer_size)
     872           16 :          CALL reallocate(amb_info%torsion_b, 1, buffer_size)
     873           16 :          CALL reallocate(amb_info%torsion_c, 1, buffer_size)
     874           16 :          CALL reallocate(amb_info%torsion_d, 1, buffer_size)
     875           16 :          CALL reallocate(amb_info%torsion_k, 1, buffer_size)
     876           16 :          CALL reallocate(amb_info%torsion_m, 1, buffer_size)
     877           16 :          CALL reallocate(amb_info%torsion_phi0, 1, buffer_size)
     878           16 :          nsize = 0
     879              :          ! Torsions containing hydrogens
     880              :          CALL post_process_torsions_info(amb_info%torsion_a, amb_info%torsion_b, &
     881              :                                          amb_info%torsion_c, amb_info%torsion_d, amb_info%torsion_k, &
     882              :                                          amb_info%torsion_m, amb_info%torsion_phi0, particle_set, nsize, &
     883           16 :                                          nphih, iph, jph, kph, lph, icph, pk, pn, phase)
     884              :          ! Torsions non-containing hydrogens
     885              :          CALL post_process_torsions_info(amb_info%torsion_a, amb_info%torsion_b, &
     886              :                                          amb_info%torsion_c, amb_info%torsion_d, amb_info%torsion_k, &
     887              :                                          amb_info%torsion_m, amb_info%torsion_phi0, particle_set, nsize, &
     888           16 :                                          nphia, ip, jp, kp, lp, icp, pk, pn, phase)
     889              :          ! Shrink arrays size to the minimal request
     890           16 :          CALL reallocate(amb_info%torsion_a, 1, nsize)
     891           16 :          CALL reallocate(amb_info%torsion_b, 1, nsize)
     892           16 :          CALL reallocate(amb_info%torsion_c, 1, nsize)
     893           16 :          CALL reallocate(amb_info%torsion_d, 1, nsize)
     894           16 :          CALL reallocate(amb_info%torsion_k, 1, nsize)
     895           16 :          CALL reallocate(amb_info%torsion_m, 1, nsize)
     896           16 :          CALL reallocate(amb_info%torsion_phi0, 1, nsize)
     897              : 
     898              :          ! Sort dihedral metadata for faster lookup
     899           16 :          IF (nphih + nphia /= 0) THEN
     900           42 :             ALLOCATE (iwork(nphih + nphia))
     901           14 :             CALL sort(amb_info%raw_torsion_id, 1, nphih + nphia, 1, 5, iwork)
     902           14 :             DEALLOCATE (iwork)
     903              :          END IF
     904              : 
     905              :          ! ----------------------------------------------------------
     906              :          ! Post process of LJ parameters
     907              :          ! ----------------------------------------------------------
     908           16 :          CALL reallocate(amb_info%nonbond_a, 1, buffer_size)
     909           16 :          CALL reallocate(amb_info%nonbond_eps, 1, buffer_size)
     910           16 :          CALL reallocate(amb_info%nonbond_rmin2, 1, buffer_size)
     911              : 
     912           16 :          nsize = 0
     913              :          CALL post_process_LJ_info(amb_info%nonbond_a, amb_info%nonbond_eps, &
     914              :                                    amb_info%nonbond_rmin2, particle_set, ntypes, nsize, iac, ico, &
     915           16 :                                    cn1, cn2, natom)
     916              : 
     917              :          ! Shrink arrays size to the minimal request
     918           16 :          CALL reallocate(amb_info%nonbond_a, 1, nsize)
     919           16 :          CALL reallocate(amb_info%nonbond_eps, 1, nsize)
     920           16 :          CALL reallocate(amb_info%nonbond_rmin2, 1, nsize)
     921              : 
     922              :          ! Deallocate at the end of the dirty job
     923           16 :          DEALLOCATE (iac)
     924           16 :          DEALLOCATE (ico)
     925           16 :          DEALLOCATE (rk)
     926           16 :          DEALLOCATE (req)
     927           16 :          DEALLOCATE (tk)
     928           16 :          DEALLOCATE (teq)
     929           16 :          DEALLOCATE (pk)
     930           16 :          DEALLOCATE (pn)
     931           16 :          DEALLOCATE (phase)
     932           16 :          DEALLOCATE (cn1)
     933           16 :          DEALLOCATE (cn2)
     934           16 :          DEALLOCATE (asol)
     935           16 :          DEALLOCATE (bsol)
     936           16 :          CALL timestop(handle2)
     937              :       END IF
     938              :       ! Always Deallocate
     939           40 :       DEALLOCATE (ibh)
     940           40 :       DEALLOCATE (jbh)
     941           40 :       DEALLOCATE (icbh)
     942           40 :       DEALLOCATE (ib)
     943           40 :       DEALLOCATE (jb)
     944           40 :       DEALLOCATE (icb)
     945           40 :       DEALLOCATE (ith)
     946           40 :       DEALLOCATE (jth)
     947           40 :       DEALLOCATE (kth)
     948           40 :       DEALLOCATE (icth)
     949           40 :       DEALLOCATE (it)
     950           40 :       DEALLOCATE (jt)
     951           40 :       DEALLOCATE (kt)
     952           40 :       DEALLOCATE (ict)
     953           40 :       DEALLOCATE (iph)
     954           40 :       DEALLOCATE (jph)
     955           40 :       DEALLOCATE (kph)
     956           40 :       DEALLOCATE (lph)
     957           40 :       DEALLOCATE (icph)
     958           40 :       DEALLOCATE (ip)
     959           40 :       DEALLOCATE (jp)
     960           40 :       DEALLOCATE (kp)
     961           40 :       DEALLOCATE (lp)
     962           40 :       DEALLOCATE (icp)
     963           40 :       CALL parser_release(parser)
     964           40 :       CALL timestop(handle)
     965           40 :       RETURN
     966              :       ! Output info Format
     967              : 1000  FORMAT(T2, &
     968              :              /' NATOM  = ', i7, ' NTYPES = ', i7, ' NBONH = ', i7, ' MBONA  = ', i7, &
     969              :              /' NTHETH = ', i7, ' MTHETA = ', i7, ' NPHIH = ', i7, ' MPHIA  = ', i7, &
     970              :              /' NHPARM = ', i7, ' NPARM  = ', i7, ' NNB   = ', i7, ' NRES   = ', i7, &
     971              :              /' NBONA  = ', i7, ' NTHETA = ', i7, ' NPHIA = ', i7, ' NUMBND = ', i7, &
     972              :              /' NUMANG = ', i7, ' NPTRA  = ', i7, ' NATYP = ', i7, ' NPHB   = ', i7, &
     973              :              /' IFBOX  = ', i7, ' NMXRS  = ', i7, ' IFCAP = ', i7, ' NEXTRA = ', i7,/)
     974          160 :    END SUBROUTINE rdparm_amber_8
     975              : 
     976              : ! **************************************************************************************************
     977              : !> \brief Low level routine to identify and rename unique atom types
     978              : !> \param isymbl ...
     979              : !> \param iwork ...
     980              : !> \param i ...
     981              : !> \param istart ...
     982              : !> \param charges ...
     983              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
     984              : ! **************************************************************************************************
     985          268 :    SUBROUTINE conform_atom_type_low(isymbl, iwork, i, istart, charges)
     986              :       CHARACTER(LEN=default_string_length), DIMENSION(:) :: isymbl
     987              :       INTEGER, DIMENSION(:)                              :: iwork
     988              :       INTEGER, INTENT(IN)                                :: i
     989              :       INTEGER, INTENT(INOUT)                             :: istart
     990              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: charges
     991              : 
     992              :       CHARACTER(len=*), PARAMETER :: routineN = 'conform_atom_type_low'
     993              : 
     994              :       INTEGER                                            :: counter, gind, handle, iend, ind, isize, &
     995              :                                                             j, k, kend, kstart
     996          268 :       INTEGER, DIMENSION(:), POINTER                     :: cindx, lindx
     997              :       REAL(KIND=dp)                                      :: ctmp
     998          268 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: cwork
     999              : 
    1000          268 :       CALL timeset(routineN, handle)
    1001          268 :       iend = i - 1
    1002          268 :       isize = iend - istart + 1
    1003          804 :       ALLOCATE (cwork(isize))
    1004          804 :       ALLOCATE (lindx(isize))
    1005          536 :       ALLOCATE (cindx(isize))
    1006          268 :       ind = 0
    1007        79140 :       DO k = istart, iend
    1008        78872 :          ind = ind + 1
    1009        78872 :          cwork(ind) = charges(iwork(k))
    1010        79140 :          lindx(ind) = k
    1011              :       END DO
    1012          268 :       CALL sort(cwork, isize, cindx)
    1013              : 
    1014          268 :       ctmp = cwork(1)
    1015          268 :       counter = 1
    1016        78872 :       DO k = 2, isize
    1017        78872 :          IF (cwork(k) /= ctmp) THEN
    1018         1414 :             counter = counter + 1
    1019         1414 :             ctmp = cwork(k)
    1020              :          END IF
    1021              :       END DO
    1022          268 :       IF (counter /= 1) THEN
    1023          154 :          counter = 1
    1024          154 :          kstart = 1
    1025          154 :          ctmp = cwork(1)
    1026        12778 :          DO k = 2, isize
    1027        12778 :             IF (cwork(k) /= ctmp) THEN
    1028              :                kend = k - 1
    1029        12364 :                DO j = kstart, kend
    1030        10950 :                   gind = lindx(cindx(j))
    1031        10950 :                   IF (LEN_TRIM(isymbl(gind)) + LEN_TRIM(ADJUSTL(cp_to_string(counter))) > &
    1032        10950 :                       LEN(isymbl(gind))) CPABORT("AMBER charge kind name exceeds string length")
    1033        12364 :                   isymbl(gind) = TRIM(isymbl(gind))//ADJUSTL(cp_to_string(counter))
    1034              :                END DO
    1035         1414 :                counter = counter + 1
    1036         1414 :                ctmp = cwork(k)
    1037         1414 :                kstart = k
    1038              :             END IF
    1039              :          END DO
    1040              :          kend = k - 1
    1041         1982 :          DO j = kstart, kend
    1042         1828 :             gind = lindx(cindx(j))
    1043         1828 :             IF (LEN_TRIM(isymbl(gind)) + LEN_TRIM(ADJUSTL(cp_to_string(counter))) > &
    1044         1828 :                 LEN(isymbl(gind))) CPABORT("AMBER charge kind name exceeds string length")
    1045         1982 :             isymbl(gind) = TRIM(isymbl(gind))//ADJUSTL(cp_to_string(counter))
    1046              :          END DO
    1047              :       END IF
    1048          268 :       DEALLOCATE (cwork)
    1049          268 :       DEALLOCATE (lindx)
    1050          268 :       DEALLOCATE (cindx)
    1051          268 :       CALL timestop(handle)
    1052          268 :    END SUBROUTINE conform_atom_type_low
    1053              : 
    1054              : ! **************************************************************************************************
    1055              : !> \brief Resolve ambiguities introduced by the legacy AMBER charge-split
    1056              : !>        atom-kind naming scheme while preserving non-colliding names.
    1057              : !> \param isymbl Conformed atom-kind names
    1058              : !> \param raw_isymbl Original AMBER atom types
    1059              : ! **************************************************************************************************
    1060           24 :    SUBROUTINE resolve_atom_type_collisions(isymbl, raw_isymbl)
    1061              :       CHARACTER(LEN=default_string_length), &
    1062              :          DIMENSION(:), INTENT(INOUT)                     :: isymbl
    1063              :       CHARACTER(LEN=default_string_length), &
    1064              :          DIMENSION(:), INTENT(IN)                        :: raw_isymbl
    1065              : 
    1066              :       CHARACTER(len=*), PARAMETER :: routineN = 'resolve_atom_type_collisions'
    1067              : 
    1068              :       CHARACTER(LEN=default_string_length)               :: base_name, candidate, suffix
    1069              :       CHARACTER(LEN=default_string_length), &
    1070           24 :          ALLOCATABLE, DIMENSION(:)                       :: sorted_labels
    1071              :       INTEGER                                            :: finish, handle, idx, jdx, keeper, n, &
    1072              :                                                             nsep, p, q, raw_len, start
    1073           24 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: order
    1074              :       LOGICAL                                            :: collision, seen_type
    1075              : 
    1076           24 :       CALL timeset(routineN, handle)
    1077              : 
    1078           24 :       n = SIZE(isymbl)
    1079           24 :       CPASSERT(SIZE(raw_isymbl) == n)
    1080              : 
    1081           72 :       ALLOCATE (sorted_labels(n))
    1082           72 :       ALLOCATE (order(n))
    1083              : 
    1084              :       ! Sort a copy of the legacy-generated labels.  Equal labels then
    1085              :       ! form contiguous groups, while order maps back to isymbl/raw_isymbl.
    1086        78896 :       sorted_labels(:) = isymbl
    1087           24 :       CALL sort(sorted_labels, n, order)
    1088              : 
    1089           24 :       start = 1
    1090         1680 :       DO WHILE (start <= n)
    1091              :          finish = start
    1092              : 
    1093        78872 :          DO WHILE (finish < n)
    1094        78848 :             IF (sorted_labels(finish + 1) /= sorted_labels(start)) EXIT
    1095         1656 :             finish = finish + 1
    1096              :          END DO
    1097              : 
    1098         1656 :          IF (finish > start) THEN
    1099         1372 :             keeper = order(start)
    1100         1372 :             collision = .FALSE.
    1101              : 
    1102              :             ! Repeated atoms of the same original AMBER type are normal.
    1103              :             ! A collision exists only when one generated label represents
    1104              :             ! more than one original AMBER atom type.
    1105        78392 :             DO p = start + 1, finish
    1106        77046 :                idx = order(p)
    1107        78392 :                IF (raw_isymbl(idx) /= raw_isymbl(keeper)) THEN
    1108              :                   collision = .TRUE.
    1109              :                   EXIT
    1110              :                END IF
    1111              :             END DO
    1112              : 
    1113         1372 :             IF (collision) THEN
    1114              : 
    1115              :                ! Preserve an unsplit original AMBER atom type when its name
    1116              :                ! exactly matches the colliding legacy label.  If no such type
    1117              :                ! exists, disambiguate all identities in the collision group.
    1118          734 :                keeper = 0
    1119          734 :                DO p = start, finish
    1120          716 :                   idx = order(p)
    1121          734 :                   IF (raw_isymbl(idx) == sorted_labels(start)) THEN
    1122              :                      keeper = idx
    1123              :                      EXIT
    1124              :                   END IF
    1125              :                END DO
    1126              : 
    1127          744 :                DO p = start, finish
    1128          718 :                   idx = order(p)
    1129              : 
    1130          718 :                   IF (keeper /= 0) THEN
    1131           64 :                      IF (raw_isymbl(idx) == raw_isymbl(keeper)) CYCLE
    1132              :                   END IF
    1133              : 
    1134              :                   ! Handle each conflicting original AMBER type only once.
    1135         3660 :                   seen_type = .FALSE.
    1136         3660 :                   DO q = start, p - 1
    1137         3616 :                      jdx = order(q)
    1138         3660 :                      IF (raw_isymbl(jdx) == raw_isymbl(idx)) THEN
    1139              :                         seen_type = .TRUE.
    1140              :                         EXIT
    1141              :                      END IF
    1142              :                   END DO
    1143          708 :                   IF (seen_type) CYCLE
    1144              : 
    1145           44 :                   base_name = TRIM(raw_isymbl(idx))
    1146           44 :                   raw_len = LEN_TRIM(base_name)
    1147              : 
    1148              :                   ! A non-keeper colliding identity must have acquired a
    1149              :                   ! numeric charge-class suffix through conform_atom_type_low.
    1150           44 :                   IF (LEN_TRIM(sorted_labels(start)) <= raw_len) THEN
    1151            0 :                      CPABORT("Unable to disambiguate AMBER atom kind name")
    1152              :                   END IF
    1153              : 
    1154           44 :                   suffix = ADJUSTL(sorted_labels(start) (raw_len + 1:))
    1155           44 :                   nsep = 1
    1156              : 
    1157              :                   ! Prefer TYPE_1.  If that name already exists, use
    1158              :                   ! TYPE__1, TYPE___1, ... until an unused name is found.
    1159            0 :                   DO
    1160           44 :                      IF (raw_len + nsep + LEN_TRIM(suffix) > LEN(candidate)) THEN
    1161            0 :                         CPABORT("AMBER charge kind name exceeds string length")
    1162              :                      END IF
    1163              : 
    1164           88 :                      candidate = TRIM(base_name)//REPEAT("_", nsep)//TRIM(suffix)
    1165              : 
    1166       540450 :                      IF (.NOT. ANY(isymbl == candidate)) EXIT
    1167            0 :                      nsep = nsep + 1
    1168              :                   END DO
    1169              : 
    1170              :                   ! Rename all atoms belonging to this conflicting identity.
    1171         1442 :                   DO q = start, finish
    1172         1372 :                      jdx = order(q)
    1173         2090 :                      IF (raw_isymbl(jdx) == raw_isymbl(idx)) THEN
    1174          708 :                         isymbl(jdx) = candidate
    1175              :                      END IF
    1176              :                   END DO
    1177              : 
    1178              :                END DO
    1179              :             END IF
    1180              :          END IF
    1181              : 
    1182         1656 :          start = finish + 1
    1183              :       END DO
    1184              : 
    1185           24 :       DEALLOCATE (sorted_labels)
    1186           24 :       DEALLOCATE (order)
    1187              : 
    1188           24 :       CALL timestop(handle)
    1189           24 :    END SUBROUTINE resolve_atom_type_collisions
    1190              : 
    1191              : ! **************************************************************************************************
    1192              : !> \brief Set of Low level subroutines reading section for parmtop
    1193              : !>        reading 1 array of integers of length dim
    1194              : !> \param parser ...
    1195              : !> \param section ...
    1196              : !> \param array1 ...
    1197              : !> \param dim ...
    1198              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1199              : ! **************************************************************************************************
    1200           96 :    SUBROUTINE rd_amber_section_i1(parser, section, array1, dim)
    1201              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1202              :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: section
    1203              :       INTEGER, DIMENSION(:)                              :: array1
    1204              :       INTEGER, INTENT(IN)                                :: dim
    1205              : 
    1206              :       INTEGER                                            :: i
    1207              :       LOGICAL                                            :: my_end
    1208              : 
    1209           96 :       CALL parser_get_next_line(parser, 1, at_end=my_end)
    1210           96 :       i = 1
    1211       104626 :       DO WHILE ((i <= dim) .AND. (.NOT. my_end))
    1212       104530 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1213       114948 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1214              :          END IF
    1215       104530 :          IF (my_end) EXIT
    1216       104530 :          CALL parser_get_object(parser, array1(i))
    1217       104530 :          i = i + 1
    1218              :       END DO
    1219              :       ! Trigger end of file aborting
    1220           96 :       IF (my_end .AND. (i <= dim)) THEN
    1221              :          CALL cp_abort(__LOCATION__, &
    1222            0 :                        "End of file while reading section "//TRIM(section)//" in amber topology file!")
    1223              :       END IF
    1224           96 :    END SUBROUTINE rd_amber_section_i1
    1225              : 
    1226              : ! **************************************************************************************************
    1227              : !> \brief Set of Low level subroutines reading section for parmtop
    1228              : !>        reading 3 arrays of integers of length dim
    1229              : !> \param parser ...
    1230              : !> \param section ...
    1231              : !> \param array1 ...
    1232              : !> \param array2 ...
    1233              : !> \param array3 ...
    1234              : !> \param dim ...
    1235              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1236              : ! **************************************************************************************************
    1237           80 :    SUBROUTINE rd_amber_section_i3(parser, section, array1, array2, array3, dim)
    1238              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1239              :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: section
    1240              :       INTEGER, DIMENSION(:)                              :: array1, array2, array3
    1241              :       INTEGER, INTENT(IN)                                :: dim
    1242              : 
    1243              :       INTEGER                                            :: i
    1244              :       LOGICAL                                            :: my_end
    1245              : 
    1246           80 :       CALL parser_get_next_line(parser, 1, at_end=my_end)
    1247           80 :       i = 1
    1248       114122 :       DO WHILE ((i <= dim) .AND. (.NOT. my_end))
    1249              :          !array1
    1250       114042 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1251       125400 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1252              :          END IF
    1253       114042 :          IF (my_end) EXIT
    1254       114042 :          CALL parser_get_object(parser, array1(i))
    1255              :          !array2
    1256       114042 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1257       125470 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1258              :          END IF
    1259       114042 :          IF (my_end) EXIT
    1260       114042 :          CALL parser_get_object(parser, array2(i))
    1261              :          !array3
    1262       114042 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1263       125428 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1264              :          END IF
    1265       114042 :          IF (my_end) EXIT
    1266       114042 :          CALL parser_get_object(parser, array3(i))
    1267       114042 :          i = i + 1
    1268              :       END DO
    1269              :       ! Trigger end of file aborting
    1270           80 :       IF (my_end .AND. (i <= dim)) THEN
    1271              :          CALL cp_abort(__LOCATION__, &
    1272            0 :                        "End of file while reading section "//TRIM(section)//" in amber topology file!")
    1273              :       END IF
    1274           80 :    END SUBROUTINE rd_amber_section_i3
    1275              : 
    1276              : ! **************************************************************************************************
    1277              : !> \brief Set of Low level subroutines reading section for parmtop
    1278              : !>        reading 4 arrays of integers of length dim
    1279              : !> \param parser ...
    1280              : !> \param section ...
    1281              : !> \param array1 ...
    1282              : !> \param array2 ...
    1283              : !> \param array3 ...
    1284              : !> \param array4 ...
    1285              : !> \param dim ...
    1286              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1287              : ! **************************************************************************************************
    1288           80 :    SUBROUTINE rd_amber_section_i4(parser, section, array1, array2, array3, array4, dim)
    1289              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1290              :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: section
    1291              :       INTEGER, DIMENSION(:)                              :: array1, array2, array3, array4
    1292              :       INTEGER, INTENT(IN)                                :: dim
    1293              : 
    1294              :       INTEGER                                            :: i
    1295              :       LOGICAL                                            :: my_end
    1296              : 
    1297           80 :       CALL parser_get_next_line(parser, 1, at_end=my_end)
    1298           80 :       i = 1
    1299        91556 :       DO WHILE ((i <= dim) .AND. (.NOT. my_end))
    1300              :          !array1
    1301        91476 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1302       109730 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1303              :          END IF
    1304        91476 :          IF (my_end) EXIT
    1305        91476 :          CALL parser_get_object(parser, array1(i))
    1306              :          !array2
    1307        91476 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1308        91476 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1309              :          END IF
    1310        91476 :          IF (my_end) EXIT
    1311        91476 :          CALL parser_get_object(parser, array2(i))
    1312              :          !array3
    1313        91476 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1314       109766 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1315              :          END IF
    1316        91476 :          IF (my_end) EXIT
    1317        91476 :          CALL parser_get_object(parser, array3(i))
    1318              :          !array4
    1319        91476 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1320        91476 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1321              :          END IF
    1322        91476 :          IF (my_end) EXIT
    1323        91476 :          CALL parser_get_object(parser, array4(i))
    1324        91476 :          i = i + 1
    1325              :       END DO
    1326              :       ! Trigger end of file aborting
    1327           80 :       IF (my_end .AND. (i <= dim)) THEN
    1328              :          CALL cp_abort(__LOCATION__, &
    1329            0 :                        "End of file while reading section "//TRIM(section)//" in amber topology file!")
    1330              :       END IF
    1331           80 :    END SUBROUTINE rd_amber_section_i4
    1332              : 
    1333              : ! **************************************************************************************************
    1334              : !> \brief Set of Low level subroutines reading section for parmtop
    1335              : !>        reading 5 arrays of integers of length dim
    1336              : !> \param parser ...
    1337              : !> \param section ...
    1338              : !> \param array1 ...
    1339              : !> \param array2 ...
    1340              : !> \param array3 ...
    1341              : !> \param array4 ...
    1342              : !> \param array5 ...
    1343              : !> \param dim ...
    1344              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1345              : ! **************************************************************************************************
    1346           80 :    SUBROUTINE rd_amber_section_i5(parser, section, array1, array2, array3, array4, &
    1347           80 :                                   array5, dim)
    1348              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1349              :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: section
    1350              :       INTEGER, DIMENSION(:)                              :: array1, array2, array3, array4, array5
    1351              :       INTEGER, INTENT(IN)                                :: dim
    1352              : 
    1353              :       INTEGER                                            :: i
    1354              :       LOGICAL                                            :: my_end
    1355              : 
    1356           80 :       CALL parser_get_next_line(parser, 1, at_end=my_end)
    1357           80 :       i = 1
    1358       102004 :       DO WHILE ((i <= dim) .AND. (.NOT. my_end))
    1359              :          !array1
    1360       101924 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1361       152842 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1362              :          END IF
    1363       101924 :          IF (my_end) EXIT
    1364       101924 :          CALL parser_get_object(parser, array1(i))
    1365              :          !array2
    1366       101924 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1367       101924 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1368              :          END IF
    1369       101924 :          IF (my_end) EXIT
    1370       101924 :          CALL parser_get_object(parser, array2(i))
    1371              :          !array3
    1372       101924 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1373       101924 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1374              :          END IF
    1375       101924 :          IF (my_end) EXIT
    1376       101924 :          CALL parser_get_object(parser, array3(i))
    1377              :          !array4
    1378       101924 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1379       101924 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1380              :          END IF
    1381       101924 :          IF (my_end) EXIT
    1382       101924 :          CALL parser_get_object(parser, array4(i))
    1383              :          !array5
    1384       101924 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1385       101924 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1386              :          END IF
    1387       101924 :          IF (my_end) EXIT
    1388       101924 :          CALL parser_get_object(parser, array5(i))
    1389       101924 :          i = i + 1
    1390              :       END DO
    1391              :       ! Trigger end of file aborting
    1392           80 :       IF (my_end .AND. (i <= dim)) THEN
    1393              :          CALL cp_abort(__LOCATION__, &
    1394            0 :                        "End of file while reading section "//TRIM(section)//" in amber topology file!")
    1395              :       END IF
    1396           80 :    END SUBROUTINE rd_amber_section_i5
    1397              : 
    1398              : ! **************************************************************************************************
    1399              : !> \brief Set of Low level subroutines reading section for parmtop
    1400              : !>        reading 1 array of strings of length dim
    1401              : !> \param parser ...
    1402              : !> \param section ...
    1403              : !> \param array1 ...
    1404              : !> \param dim ...
    1405              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1406              : ! **************************************************************************************************
    1407           48 :    SUBROUTINE rd_amber_section_c1(parser, section, array1, dim)
    1408              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1409              :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: section
    1410              :       CHARACTER(LEN=default_string_length), DIMENSION(:) :: array1
    1411              :       INTEGER, INTENT(IN)                                :: dim
    1412              : 
    1413              :       INTEGER                                            :: i
    1414              :       LOGICAL                                            :: my_end
    1415              : 
    1416           48 :       CALL parser_get_next_line(parser, 1, at_end=my_end)
    1417           48 :       i = 1
    1418       101654 :       DO WHILE ((i <= dim) .AND. (.NOT. my_end))
    1419       101606 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1420       106672 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1421              :          END IF
    1422       101606 :          IF (my_end) EXIT
    1423       101606 :          CALL parser_get_object(parser, array1(i), lower_to_upper=.TRUE.)
    1424       101606 :          i = i + 1
    1425              :       END DO
    1426              :       ! Trigger end of file aborting
    1427           48 :       IF (my_end .AND. (i <= dim)) THEN
    1428              :          CALL cp_abort(__LOCATION__, &
    1429            0 :                        "End of file while reading section "//TRIM(section)//" in amber topology file!")
    1430              :       END IF
    1431           48 :    END SUBROUTINE rd_amber_section_c1
    1432              : 
    1433              : ! **************************************************************************************************
    1434              : !> \brief Set of Low level subroutines reading section for parmtop
    1435              : !>        reading 1 array of strings of length dim
    1436              : !> \param parser ...
    1437              : !> \param section ...
    1438              : !> \param array1 ...
    1439              : !> \param dim ...
    1440              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1441              : ! **************************************************************************************************
    1442          224 :    SUBROUTINE rd_amber_section_r1(parser, section, array1, dim)
    1443              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1444              :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: section
    1445              :       REAL(KIND=dp), DIMENSION(:)                        :: array1
    1446              :       INTEGER, INTENT(IN)                                :: dim
    1447              : 
    1448              :       INTEGER                                            :: i
    1449              :       LOGICAL                                            :: my_end
    1450              : 
    1451          224 :       CALL parser_get_next_line(parser, 1, at_end=my_end)
    1452          224 :       i = 1
    1453       162398 :       DO WHILE ((i <= dim) .AND. (.NOT. my_end))
    1454       162174 :          IF (parser_test_next_token(parser) == "EOL") THEN
    1455       194502 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1456              :          END IF
    1457       162174 :          IF (my_end) EXIT
    1458       162174 :          CALL parser_get_object(parser, array1(i))
    1459       162174 :          i = i + 1
    1460              :       END DO
    1461              :       ! Trigger end of file aborting
    1462          224 :       IF (my_end .AND. (i <= dim)) THEN
    1463              :          CALL cp_abort(__LOCATION__, &
    1464            0 :                        "End of file while reading section "//TRIM(section)//" in amber topology file!")
    1465              :       END IF
    1466          224 :    END SUBROUTINE rd_amber_section_r1
    1467              : 
    1468              : ! **************************************************************************************************
    1469              : !> \brief Check the version of the AMBER topology file (we can handle from v8 on)
    1470              : !> \param parser ...
    1471              : !> \param section ...
    1472              : !> \param input_format ...
    1473              : !> \return ...
    1474              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1475              : ! **************************************************************************************************
    1476         1560 :    FUNCTION get_section_parmtop(parser, section, input_format) RESULT(another_section)
    1477              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1478              :       CHARACTER(LEN=default_string_length), INTENT(OUT)  :: section, input_format
    1479              :       LOGICAL                                            :: another_section
    1480              : 
    1481              :       INTEGER                                            :: end_f, indflag, start_f
    1482              :       LOGICAL                                            :: found, my_end
    1483              : 
    1484         1560 :       CALL parser_search_string(parser, "%FLAG", .TRUE., found, begin_line=.TRUE.)
    1485         1560 :       IF (found) THEN
    1486              :          ! section label
    1487         1520 :          indflag = INDEX(parser%input_line, "%FLAG") + LEN_TRIM("%FLAG")
    1488         3040 :          DO WHILE (INDEX(parser%input_line(indflag:indflag), " ") /= 0)
    1489         1520 :             indflag = indflag + 1
    1490              :          END DO
    1491         1520 :          section = TRIM(parser%input_line(indflag:))
    1492              :          ! Input format
    1493         1520 :          CALL parser_get_next_line(parser, 1, at_end=my_end)
    1494         1520 :          IF (INDEX(parser%input_line, "%FORMAT") == 0 .OR. my_end) THEN
    1495            0 :             CPABORT("Expecting %FORMAT. Not found! Abort reading of AMBER topology file!")
    1496              :          END IF
    1497              : 
    1498         1520 :          start_f = INDEX(parser%input_line, "(")
    1499         1520 :          end_f = INDEX(parser%input_line, ")")
    1500         1520 :          input_format = parser%input_line(start_f:end_f)
    1501              :          another_section = .TRUE.
    1502              :       ELSE
    1503              :          another_section = .FALSE.
    1504              :       END IF
    1505         1560 :    END FUNCTION get_section_parmtop
    1506              : 
    1507              : ! **************************************************************************************************
    1508              : !> \brief Check the version of the AMBER topology file (we can handle from v8 on)
    1509              : !> \param parser ...
    1510              : !> \param output_unit ...
    1511              : !> \return ...
    1512              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1513              : ! **************************************************************************************************
    1514           40 :    FUNCTION check_amber_8_std(parser, output_unit) RESULT(found_AMBER_V8)
    1515              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1516              :       INTEGER, INTENT(IN)                                :: output_unit
    1517              :       LOGICAL                                            :: found_AMBER_V8
    1518              : 
    1519           40 :       CALL parser_search_string(parser, "%VERSION ", .TRUE., found_AMBER_V8, begin_line=.TRUE.)
    1520           40 :       IF (.NOT. found_AMBER_V8) THEN
    1521              :          CALL cp_abort(__LOCATION__, &
    1522              :                        "This is not an AMBER V.8 PRMTOP format file. Cannot interpret older "// &
    1523            0 :                        "AMBER file formats. ")
    1524              :       END IF
    1525           43 :       IF (output_unit > 0) WRITE (output_unit, '(" AMBER_INFO| ",A)') "Amber PrmTop V.8 or greater.", &
    1526            6 :          TRIM(parser%input_line)
    1527              : 
    1528           40 :    END FUNCTION check_amber_8_std
    1529              : 
    1530              : ! **************************************************************************************************
    1531              : !> \brief Post processing of forcefield information related to bonds
    1532              : !> \param label_a ...
    1533              : !> \param label_b ...
    1534              : !> \param k ...
    1535              : !> \param r0 ...
    1536              : !> \param particle_set ...
    1537              : !> \param ibond ...
    1538              : !> \param nbond ...
    1539              : !> \param ib ...
    1540              : !> \param jb ...
    1541              : !> \param icb ...
    1542              : !> \param rk ...
    1543              : !> \param req ...
    1544              : !> \author Teodoro Laino [tlaino] - 11.2008
    1545              : ! **************************************************************************************************
    1546           32 :    SUBROUTINE post_process_bonds_info(label_a, label_b, k, r0, particle_set, ibond, &
    1547           32 :                                       nbond, ib, jb, icb, rk, req)
    1548              :       CHARACTER(LEN=default_string_length), &
    1549              :          DIMENSION(:), POINTER                           :: label_a, label_b
    1550              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: k, r0
    1551              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1552              :       INTEGER, INTENT(INOUT)                             :: ibond
    1553              :       INTEGER, INTENT(IN)                                :: nbond
    1554              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: ib, jb, icb
    1555              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rk, req
    1556              : 
    1557              :       CHARACTER(len=*), PARAMETER :: routineN = 'post_process_bonds_info'
    1558              : 
    1559              :       CHARACTER(LEN=default_string_length)               :: name_atm_a, name_atm_b
    1560              :       CHARACTER(LEN=default_string_length), &
    1561           32 :          ALLOCATABLE, DIMENSION(:, :)                    :: work_label
    1562              :       INTEGER                                            :: handle, i
    1563           32 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: iwork
    1564              :       LOGICAL                                            :: l_dum
    1565              : 
    1566           32 :       CALL timeset(routineN, handle)
    1567           32 :       IF (nbond /= 0) THEN
    1568           90 :          ALLOCATE (work_label(2, nbond))
    1569           90 :          ALLOCATE (iwork(nbond))
    1570        56862 :          DO i = 1, nbond
    1571        56832 :             name_atm_a = particle_set(ib(i))%atomic_kind%name
    1572        56832 :             name_atm_b = particle_set(jb(i))%atomic_kind%name
    1573        56832 :             l_dum = qmmm_ff_precond_only_qm(id1=name_atm_a, id2=name_atm_b)
    1574        56832 :             work_label(1, i) = name_atm_a
    1575        56862 :             work_label(2, i) = name_atm_b
    1576              :          END DO
    1577           30 :          CALL sort(work_label, 1, nbond, 1, 2, iwork)
    1578              : 
    1579           30 :          ibond = ibond + 1
    1580              :          ! In case we need more space ... give it up...
    1581           30 :          IF (ibond > SIZE(label_a)) THEN
    1582            4 :             CALL reallocate(label_a, 1, INT(buffer_size + ibond*1.5_dp))
    1583            4 :             CALL reallocate(label_b, 1, INT(buffer_size + ibond*1.5_dp))
    1584            4 :             CALL reallocate(k, 1, INT(buffer_size + ibond*1.5_dp))
    1585            4 :             CALL reallocate(r0, 1, INT(buffer_size + ibond*1.5_dp))
    1586              :          END IF
    1587           30 :          label_a(ibond) = work_label(1, 1)
    1588           30 :          label_b(ibond) = work_label(2, 1)
    1589           30 :          k(ibond) = rk(icb(iwork(1)))
    1590           30 :          r0(ibond) = req(icb(iwork(1)))
    1591              : 
    1592        56832 :          DO i = 2, nbond
    1593        56802 :             IF ((work_label(1, i) /= label_a(ibond)) .OR. &
    1594           30 :                 (work_label(2, i) /= label_b(ibond))) THEN
    1595         1716 :                ibond = ibond + 1
    1596              :                ! In case we need more space ... give it up...
    1597         1716 :                IF (ibond > SIZE(label_a)) THEN
    1598           88 :                   CALL reallocate(label_a, 1, INT(buffer_size + ibond*1.5_dp))
    1599           88 :                   CALL reallocate(label_b, 1, INT(buffer_size + ibond*1.5_dp))
    1600           88 :                   CALL reallocate(k, 1, INT(buffer_size + ibond*1.5_dp))
    1601           88 :                   CALL reallocate(r0, 1, INT(buffer_size + ibond*1.5_dp))
    1602              :                END IF
    1603         1716 :                label_a(ibond) = work_label(1, i)
    1604         1716 :                label_b(ibond) = work_label(2, i)
    1605         1716 :                k(ibond) = rk(icb(iwork(i)))
    1606         1716 :                r0(ibond) = req(icb(iwork(i)))
    1607              :             END IF
    1608              :          END DO
    1609              : 
    1610           30 :          DEALLOCATE (work_label)
    1611           30 :          DEALLOCATE (iwork)
    1612              :       END IF
    1613           32 :       CALL timestop(handle)
    1614           32 :    END SUBROUTINE post_process_bonds_info
    1615              : 
    1616              : ! **************************************************************************************************
    1617              : !> \brief Post processing of forcefield information related to bends
    1618              : !> \param label_a ...
    1619              : !> \param label_b ...
    1620              : !> \param label_c ...
    1621              : !> \param k ...
    1622              : !> \param theta0 ...
    1623              : !> \param particle_set ...
    1624              : !> \param itheta ...
    1625              : !> \param ntheta ...
    1626              : !> \param it ...
    1627              : !> \param jt ...
    1628              : !> \param kt ...
    1629              : !> \param ict ...
    1630              : !> \param tk ...
    1631              : !> \param teq ...
    1632              : !> \author Teodoro Laino [tlaino] - 11.2008
    1633              : ! **************************************************************************************************
    1634           32 :    SUBROUTINE post_process_bends_info(label_a, label_b, label_c, k, theta0, &
    1635           32 :                                       particle_set, itheta, ntheta, it, jt, kt, ict, tk, teq)
    1636              :       CHARACTER(LEN=default_string_length), &
    1637              :          DIMENSION(:), POINTER                           :: label_a, label_b, label_c
    1638              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: k, theta0
    1639              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1640              :       INTEGER, INTENT(INOUT)                             :: itheta
    1641              :       INTEGER, INTENT(IN)                                :: ntheta
    1642              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: it, jt, kt, ict
    1643              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: tk, teq
    1644              : 
    1645              :       CHARACTER(len=*), PARAMETER :: routineN = 'post_process_bends_info'
    1646              : 
    1647              :       CHARACTER(LEN=default_string_length)               :: name_atm_a, name_atm_b, name_atm_c
    1648              :       CHARACTER(LEN=default_string_length), &
    1649           32 :          ALLOCATABLE, DIMENSION(:, :)                    :: work_label
    1650              :       INTEGER                                            :: handle, i
    1651           32 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: iwork
    1652              :       LOGICAL                                            :: l_dum
    1653              : 
    1654           32 :       CALL timeset(routineN, handle)
    1655           32 :       IF (ntheta /= 0) THEN
    1656           90 :          ALLOCATE (work_label(3, ntheta))
    1657           90 :          ALLOCATE (iwork(ntheta))
    1658        45456 :          DO i = 1, ntheta
    1659        45426 :             name_atm_a = particle_set(it(i))%atomic_kind%name
    1660        45426 :             name_atm_b = particle_set(jt(i))%atomic_kind%name
    1661        45426 :             name_atm_c = particle_set(kt(i))%atomic_kind%name
    1662              :             l_dum = qmmm_ff_precond_only_qm(id1=name_atm_a, id2=name_atm_b, &
    1663        45426 :                                             id3=name_atm_c)
    1664        45426 :             work_label(1, i) = name_atm_a
    1665        45426 :             work_label(2, i) = name_atm_b
    1666        45456 :             work_label(3, i) = name_atm_c
    1667              :          END DO
    1668              : 
    1669           30 :          CALL sort(work_label, 1, ntheta, 1, 3, iwork)
    1670              : 
    1671           30 :          itheta = itheta + 1
    1672              :          ! In case we need more space ... give it up...
    1673           30 :          IF (itheta > SIZE(label_a)) THEN
    1674            2 :             CALL reallocate(label_a, 1, INT(buffer_size + itheta*1.5_dp))
    1675            2 :             CALL reallocate(label_b, 1, INT(buffer_size + itheta*1.5_dp))
    1676            2 :             CALL reallocate(label_c, 1, INT(buffer_size + itheta*1.5_dp))
    1677            2 :             CALL reallocate(k, 1, INT(buffer_size + itheta*1.5_dp))
    1678            2 :             CALL reallocate(theta0, 1, INT(buffer_size + itheta*1.5_dp))
    1679              :          END IF
    1680           30 :          label_a(itheta) = work_label(1, 1)
    1681           30 :          label_b(itheta) = work_label(2, 1)
    1682           30 :          label_c(itheta) = work_label(3, 1)
    1683           30 :          k(itheta) = tk(ict(iwork(1)))
    1684           30 :          theta0(itheta) = teq(ict(iwork(1)))
    1685              : 
    1686        45426 :          DO i = 2, ntheta
    1687              :             IF ((work_label(1, i) /= label_a(itheta)) .OR. &
    1688        45396 :                 (work_label(2, i) /= label_b(itheta)) .OR. &
    1689           30 :                 (work_label(3, i) /= label_c(itheta))) THEN
    1690         3642 :                itheta = itheta + 1
    1691              :                ! In case we need more space ... give it up...
    1692         3642 :                IF (itheta > SIZE(label_a)) THEN
    1693          110 :                   CALL reallocate(label_a, 1, INT(buffer_size + itheta*1.5_dp))
    1694          110 :                   CALL reallocate(label_b, 1, INT(buffer_size + itheta*1.5_dp))
    1695          110 :                   CALL reallocate(label_c, 1, INT(buffer_size + itheta*1.5_dp))
    1696          110 :                   CALL reallocate(k, 1, INT(buffer_size + itheta*1.5_dp))
    1697          110 :                   CALL reallocate(theta0, 1, INT(buffer_size + itheta*1.5_dp))
    1698              :                END IF
    1699         3642 :                label_a(itheta) = work_label(1, i)
    1700         3642 :                label_b(itheta) = work_label(2, i)
    1701         3642 :                label_c(itheta) = work_label(3, i)
    1702         3642 :                k(itheta) = tk(ict(iwork(i)))
    1703         3642 :                theta0(itheta) = teq(ict(iwork(i)))
    1704              :             END IF
    1705              :          END DO
    1706              : 
    1707           30 :          DEALLOCATE (work_label)
    1708           30 :          DEALLOCATE (iwork)
    1709              :       END IF
    1710           32 :       CALL timestop(handle)
    1711           32 :    END SUBROUTINE post_process_bends_info
    1712              : 
    1713              : ! **************************************************************************************************
    1714              : !> \brief Post processing of forcefield information related to torsions
    1715              : !> \param label_a ...
    1716              : !> \param label_b ...
    1717              : !> \param label_c ...
    1718              : !> \param label_d ...
    1719              : !> \param k ...
    1720              : !> \param m ...
    1721              : !> \param phi0 ...
    1722              : !> \param particle_set ...
    1723              : !> \param iphi ...
    1724              : !> \param nphi ...
    1725              : !> \param ip ...
    1726              : !> \param jp ...
    1727              : !> \param kp ...
    1728              : !> \param lp ...
    1729              : !> \param icp ...
    1730              : !> \param pk ...
    1731              : !> \param pn ...
    1732              : !> \param phase ...
    1733              : !> \author Teodoro Laino [tlaino] - 11.2008
    1734              : ! **************************************************************************************************
    1735           32 :    SUBROUTINE post_process_torsions_info(label_a, label_b, label_c, label_d, k, &
    1736           32 :                                          m, phi0, particle_set, iphi, nphi, ip, jp, kp, lp, icp, pk, pn, phase)
    1737              :       CHARACTER(LEN=default_string_length), &
    1738              :          DIMENSION(:), POINTER                           :: label_a, label_b, label_c, label_d
    1739              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: k
    1740              :       INTEGER, DIMENSION(:), POINTER                     :: m
    1741              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: phi0
    1742              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1743              :       INTEGER, INTENT(INOUT)                             :: iphi
    1744              :       INTEGER, INTENT(IN)                                :: nphi
    1745              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: ip, jp, kp, lp, icp
    1746              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: pk, pn, phase
    1747              : 
    1748              :       CHARACTER(len=*), PARAMETER :: routineN = 'post_process_torsions_info'
    1749              : 
    1750              :       CHARACTER(LEN=default_string_length)               :: name_atm_a, name_atm_b, name_atm_c, &
    1751              :                                                             name_atm_d
    1752              :       CHARACTER(LEN=default_string_length), &
    1753           32 :          ALLOCATABLE, DIMENSION(:, :)                    :: work_label
    1754              :       INTEGER                                            :: handle, i
    1755           32 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: iwork
    1756              :       LOGICAL                                            :: l_dum
    1757              : 
    1758           32 :       CALL timeset(routineN, handle)
    1759           32 :       IF (nphi /= 0) THEN
    1760           84 :          ALLOCATE (work_label(6, nphi))
    1761           84 :          ALLOCATE (iwork(nphi))
    1762        50488 :          DO i = 1, nphi
    1763        50460 :             name_atm_a = particle_set(ip(i))%atomic_kind%name
    1764        50460 :             name_atm_b = particle_set(jp(i))%atomic_kind%name
    1765        50460 :             name_atm_c = particle_set(kp(i))%atomic_kind%name
    1766        50460 :             name_atm_d = particle_set(lp(i))%atomic_kind%name
    1767              :             l_dum = qmmm_ff_precond_only_qm(id1=name_atm_a, id2=name_atm_b, &
    1768        50460 :                                             id3=name_atm_c, id4=name_atm_d)
    1769        50460 :             work_label(1, i) = name_atm_a
    1770        50460 :             work_label(2, i) = name_atm_b
    1771        50460 :             work_label(3, i) = name_atm_c
    1772        50460 :             work_label(4, i) = name_atm_d
    1773              :             ! Phase and multiplicity must be kept into account
    1774              :             ! for the ordering of the torsions
    1775        50460 :             work_label(5, i) = TRIM(ADJUSTL(cp_to_string(phase(icp(i)))))
    1776        50488 :             work_label(6, i) = TRIM(ADJUSTL(cp_to_string(pn(icp(i)))))
    1777              :          END DO
    1778              : 
    1779           28 :          CALL sort(work_label, 1, nphi, 1, 6, iwork)
    1780              : 
    1781           28 :          iphi = iphi + 1
    1782              :          ! In case we need more space ... give it up...
    1783           28 :          IF (iphi > SIZE(label_a)) THEN
    1784            0 :             CALL reallocate(label_a, 1, INT(buffer_size + iphi*1.5_dp))
    1785            0 :             CALL reallocate(label_b, 1, INT(buffer_size + iphi*1.5_dp))
    1786            0 :             CALL reallocate(label_c, 1, INT(buffer_size + iphi*1.5_dp))
    1787            0 :             CALL reallocate(label_d, 1, INT(buffer_size + iphi*1.5_dp))
    1788            0 :             CALL reallocate(k, 1, INT(buffer_size + iphi*1.5_dp))
    1789            0 :             CALL reallocate(m, 1, INT(buffer_size + iphi*1.5_dp))
    1790            0 :             CALL reallocate(phi0, 1, INT(buffer_size + iphi*1.5_dp))
    1791              :          END IF
    1792           28 :          label_a(iphi) = work_label(1, 1)
    1793           28 :          label_b(iphi) = work_label(2, 1)
    1794           28 :          label_c(iphi) = work_label(3, 1)
    1795           28 :          label_d(iphi) = work_label(4, 1)
    1796           28 :          k(iphi) = pk(icp(iwork(1)))
    1797           28 :          m(iphi) = NINT(pn(icp(iwork(1))))
    1798           28 :          IF (m(iphi) - pn(icp(iwork(1))) > EPSILON(1.0_dp)) THEN
    1799            0 :             CPABORT("Non-integer torsions not supported")
    1800              :          END IF
    1801              : 
    1802           28 :          phi0(iphi) = phase(icp(iwork(1)))
    1803              : 
    1804        50460 :          DO i = 2, nphi
    1805              :             ! We don't consider the possibility that a torsion can have same
    1806              :             ! phase, periodicity but different value of k.. in this case the
    1807              :             ! potential should be summed-up
    1808              :             IF ((work_label(1, i) /= label_a(iphi)) .OR. &
    1809              :                 (work_label(2, i) /= label_b(iphi)) .OR. &
    1810              :                 (work_label(3, i) /= label_c(iphi)) .OR. &
    1811              :                 (work_label(4, i) /= label_d(iphi)) .OR. &
    1812        50432 :                 (pn(icp(iwork(i))) /= m(iphi)) .OR. &
    1813           28 :                 (phase(icp(iwork(i))) /= phi0(iphi))) THEN
    1814        10096 :                iphi = iphi + 1
    1815              :                ! In case we need more space ... give it up...
    1816        10096 :                IF (iphi > SIZE(label_a)) THEN
    1817          138 :                   CALL reallocate(label_a, 1, INT(buffer_size + iphi*1.5_dp))
    1818          138 :                   CALL reallocate(label_b, 1, INT(buffer_size + iphi*1.5_dp))
    1819          138 :                   CALL reallocate(label_c, 1, INT(buffer_size + iphi*1.5_dp))
    1820          138 :                   CALL reallocate(label_d, 1, INT(buffer_size + iphi*1.5_dp))
    1821          138 :                   CALL reallocate(k, 1, INT(buffer_size + iphi*1.5_dp))
    1822          138 :                   CALL reallocate(m, 1, INT(buffer_size + iphi*1.5_dp))
    1823          138 :                   CALL reallocate(phi0, 1, INT(buffer_size + iphi*1.5_dp))
    1824              :                END IF
    1825        10096 :                label_a(iphi) = work_label(1, i)
    1826        10096 :                label_b(iphi) = work_label(2, i)
    1827        10096 :                label_c(iphi) = work_label(3, i)
    1828        10096 :                label_d(iphi) = work_label(4, i)
    1829        10096 :                k(iphi) = pk(icp(iwork(i)))
    1830        10096 :                m(iphi) = NINT(pn(icp(iwork(i))))
    1831        10096 :                IF (m(iphi) - pn(icp(iwork(i))) > EPSILON(1.0_dp)) THEN
    1832            0 :                   CPABORT("Non-integer torsions not supported")
    1833              :                END IF
    1834        10096 :                phi0(iphi) = phase(icp(iwork(i)))
    1835              :             END IF
    1836              :          END DO
    1837              : 
    1838           28 :          DEALLOCATE (work_label)
    1839           28 :          DEALLOCATE (iwork)
    1840              :       END IF
    1841           32 :       CALL timestop(handle)
    1842           32 :    END SUBROUTINE post_process_torsions_info
    1843              : 
    1844              : ! **************************************************************************************************
    1845              : !> \brief Post processing of forcefield information related to Lennard-Jones
    1846              : !> \param atom_label ...
    1847              : !> \param eps ...
    1848              : !> \param sigma ...
    1849              : !> \param particle_set ...
    1850              : !> \param ntypes ...
    1851              : !> \param nsize ...
    1852              : !> \param iac ...
    1853              : !> \param ico ...
    1854              : !> \param cn1 ...
    1855              : !> \param cn2 ...
    1856              : !> \param natom ...
    1857              : !> \author Teodoro Laino [tlaino] - 11.2008
    1858              : ! **************************************************************************************************
    1859           16 :    SUBROUTINE post_process_LJ_info(atom_label, eps, sigma, particle_set, &
    1860           16 :                                    ntypes, nsize, iac, ico, cn1, cn2, natom)
    1861              :       CHARACTER(LEN=default_string_length), &
    1862              :          DIMENSION(:), POINTER                           :: atom_label
    1863              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eps, sigma
    1864              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1865              :       INTEGER, INTENT(IN)                                :: ntypes
    1866              :       INTEGER, INTENT(INOUT)                             :: nsize
    1867              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: iac, ico
    1868              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: cn1, cn2
    1869              :       INTEGER, INTENT(IN)                                :: natom
    1870              : 
    1871              :       CHARACTER(len=*), PARAMETER :: routineN = 'post_process_LJ_info'
    1872              : 
    1873              :       CHARACTER(LEN=default_string_length)               :: name_atm_a
    1874              :       CHARACTER(LEN=default_string_length), &
    1875           16 :          ALLOCATABLE, DIMENSION(:)                       :: work_label
    1876              :       INTEGER                                            :: handle, i
    1877           16 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: iwork
    1878              :       LOGICAL                                            :: check, l_dum
    1879              :       REAL(KIND=dp)                                      :: F12, F6, my_eps, my_sigma, sigma6
    1880              : 
    1881           16 :       CALL timeset(routineN, handle)
    1882           48 :       ALLOCATE (work_label(natom))
    1883           48 :       ALLOCATE (iwork(natom))
    1884        78544 :       DO i = 1, natom
    1885        78528 :          name_atm_a = particle_set(i)%atomic_kind%name
    1886        78528 :          l_dum = qmmm_ff_precond_only_qm(id1=name_atm_a)
    1887        78544 :          work_label(i) = name_atm_a
    1888              :       END DO
    1889           16 :       CALL sort(work_label, natom, iwork)
    1890              : 
    1891           16 :       nsize = nsize + 1
    1892           16 :       IF (nsize > SIZE(atom_label)) THEN
    1893            0 :          CALL reallocate(atom_label, 1, INT(buffer_size + nsize*1.5_dp))
    1894            0 :          CALL reallocate(eps, 1, INT(buffer_size + nsize*1.5_dp))
    1895            0 :          CALL reallocate(sigma, 1, INT(buffer_size + nsize*1.5_dp))
    1896              :       END IF
    1897           16 :       F12 = cn1(ico(ntypes*(iac(iwork(1)) - 1) + iac(iwork(1))))
    1898           16 :       F6 = cn2(ico(ntypes*(iac(iwork(1)) - 1) + iac(iwork(1))))
    1899           16 :       check = (F6 == 0.0_dp) .EQV. (F12 == 0.0_dp)
    1900           16 :       CPASSERT(check)
    1901           16 :       my_sigma = 0.0_dp
    1902           16 :       my_eps = 0.0_dp
    1903           16 :       IF (F6 /= 0.0_dp) THEN
    1904           16 :          sigma6 = (2.0_dp*F12/F6)
    1905           16 :          my_sigma = sigma6**(1.0_dp/6.0_dp)
    1906           16 :          my_eps = F6/(2.0_dp*sigma6)
    1907              :       END IF
    1908           16 :       atom_label(nsize) = work_label(1)
    1909           16 :       sigma(nsize) = my_sigma/2.0_dp
    1910           16 :       eps(nsize) = my_eps
    1911              : 
    1912        78528 :       DO i = 2, natom
    1913        78528 :          IF (work_label(i) == atom_label(nsize)) THEN
    1914        77020 :             IF (iac(iwork(i)) /= iac(iwork(i - 1))) THEN
    1915            0 :                CPABORT("AMBER kind collision: "//TRIM(work_label(i)))
    1916              :             END IF
    1917              :          ELSE
    1918         1492 :             nsize = nsize + 1
    1919              :             ! In case we need more space ... give it up...
    1920         1492 :             IF (nsize > SIZE(atom_label)) THEN
    1921           90 :                CALL reallocate(atom_label, 1, INT(buffer_size + nsize*1.5_dp))
    1922           90 :                CALL reallocate(eps, 1, INT(buffer_size + nsize*1.5_dp))
    1923           90 :                CALL reallocate(sigma, 1, INT(buffer_size + nsize*1.5_dp))
    1924              :             END IF
    1925         1492 :             F12 = cn1(ico(ntypes*(iac(iwork(i)) - 1) + iac(iwork(i))))
    1926         1492 :             F6 = cn2(ico(ntypes*(iac(iwork(i)) - 1) + iac(iwork(i))))
    1927         1492 :             check = (F6 == 0.0_dp) .EQV. (F12 == 0.0_dp)
    1928         1492 :             CPASSERT(check)
    1929         1492 :             my_sigma = 0.0_dp
    1930         1492 :             my_eps = 0.0_dp
    1931         1492 :             IF (F6 /= 0.0_dp) THEN
    1932         1468 :                sigma6 = (2.0_dp*F12/F6)
    1933         1468 :                my_sigma = sigma6**(1.0_dp/6.0_dp)
    1934         1468 :                my_eps = F6/(2.0_dp*sigma6)
    1935              :             END IF
    1936         1492 :             atom_label(nsize) = work_label(i)
    1937         1492 :             sigma(nsize) = my_sigma/2.0_dp
    1938         1492 :             eps(nsize) = my_eps
    1939              :          END IF
    1940              :       END DO
    1941              : 
    1942           16 :       DEALLOCATE (work_label)
    1943           16 :       DEALLOCATE (iwork)
    1944           16 :       CALL timestop(handle)
    1945           16 :    END SUBROUTINE post_process_LJ_info
    1946              : 
    1947              : END MODULE topology_amber
    1948              : 
        

Generated by: LCOV version 2.0-1