LCOV - code coverage report
Current view: top level - src - topology_amber.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:4dc10b3) Lines: 862 893 96.5 %
Date: 2024-11-21 06:45:46 Functions: 16 16 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 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) &
     188           0 :             CPABORT("Error while reading CRD file. Unexpected end of file.")
     189          26 :       ELSE IF (MOD(natom, 2) /= 0) THEN
     190             :          ! In case let's handle the last atom
     191           2 :          j = natom
     192           2 :          READ (parser%input_line, *) atom_info%r(1, j), atom_info%r(2, j), atom_info%r(3, j)
     193             :          ! All these information will have to be setup elsewhere..
     194             :          ! CRD file does not contain anything related..
     195           2 :          atom_info%id_atmname(j) = str2id(s2s("__UNDEF__"))
     196           2 :          atom_info%id_molname(j) = str2id(s2s("__UNDEF__"))
     197           2 :          atom_info%id_resname(j) = str2id(s2s("__UNDEF__"))
     198           2 :          atom_info%id_element(j) = str2id(s2s("__UNDEF__"))
     199           2 :          atom_info%resid(j) = HUGE(0)
     200           2 :          atom_info%atm_mass(j) = HUGE(0.0_dp)
     201           2 :          atom_info%atm_charge(j) = -HUGE(0.0_dp)
     202           2 :          atom_info%r(1, j) = cp_unit_to_cp2k(atom_info%r(1, j), "angstrom")
     203           2 :          atom_info%r(2, j) = cp_unit_to_cp2k(atom_info%r(2, j), "angstrom")
     204           2 :          atom_info%r(3, j) = cp_unit_to_cp2k(atom_info%r(3, j), "angstrom")
     205             : 
     206           2 :          CALL parser_get_next_line(parser, 1, at_end=my_end)
     207             :       END IF
     208             : 
     209          26 :       IF (my_end) THEN
     210          20 :          CPWARN_IF(j /= natom, "No VELOCITY or BOX information found in CRD file.")
     211             :       ELSE
     212             :          ! Velocities
     213           6 :          CALL reallocate(velocity, 1, 3, 1, natom)
     214       38604 :          DO j = 1, natom - MOD(natom, 2), 2
     215       38598 :             IF (my_end) EXIT
     216       38598 :             READ (parser%input_line, *) velocity(1, j), velocity(2, j), velocity(3, j), &
     217       77196 :                velocity(1, j + 1), velocity(2, j + 1), velocity(3, j + 1)
     218             : 
     219       38598 :             velocity(1, j) = cp_unit_to_cp2k(velocity(1, j), "angstrom*ps^-1")
     220       38598 :             velocity(2, j) = cp_unit_to_cp2k(velocity(2, j), "angstrom*ps^-1")
     221       38598 :             velocity(3, j) = cp_unit_to_cp2k(velocity(3, j), "angstrom*ps^-1")
     222      154392 :             velocity(1:3, j) = velocity(1:3, j)*amber_conv_factor
     223             : 
     224       38598 :             velocity(1, j + 1) = cp_unit_to_cp2k(velocity(1, j + 1), "angstrom*ps^-1")
     225       38598 :             velocity(2, j + 1) = cp_unit_to_cp2k(velocity(2, j + 1), "angstrom*ps^-1")
     226       38598 :             velocity(3, j + 1) = cp_unit_to_cp2k(velocity(3, j + 1), "angstrom*ps^-1")
     227      154392 :             velocity(1:3, j + 1) = velocity(1:3, j + 1)*amber_conv_factor
     228             : 
     229       38604 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
     230             :          END DO
     231           6 :          setup_velocities = .TRUE.
     232           6 :          IF ((my_end) .AND. (j /= natom - MOD(natom, 2) + 1)) THEN
     233           0 :             IF (j /= natom) &
     234             :                CALL cp_warn(__LOCATION__, &
     235             :                             "No VELOCITY information found in CRD file. Ignoring BOX information. "// &
     236           0 :                             "Please provide the BOX information directly from the main CP2K input! ")
     237             :             setup_velocities = .FALSE.
     238           6 :          ELSE IF (MOD(natom, 2) /= 0) THEN
     239             :             ! In case let's handle the last atom
     240           0 :             j = natom
     241           0 :             READ (parser%input_line, *) velocity(1, j), velocity(2, j), velocity(3, j)
     242             : 
     243           0 :             velocity(1, j) = cp_unit_to_cp2k(velocity(1, j), "angstrom*ps^-1")
     244           0 :             velocity(2, j) = cp_unit_to_cp2k(velocity(2, j), "angstrom*ps^-1")
     245           0 :             velocity(3, j) = cp_unit_to_cp2k(velocity(3, j), "angstrom*ps^-1")
     246           0 :             velocity(1:3, j) = velocity(1:3, j)*amber_conv_factor
     247             : 
     248           0 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
     249             :          END IF
     250             :          IF (setup_velocities) THEN
     251           6 :             velocity_section => section_vals_get_subs_vals(subsys_section, "VELOCITY")
     252             :             CALL section_velocity_val_set(velocity_section, velocity=velocity, &
     253           6 :                                           conv_factor=1.0_dp)
     254             :          END IF
     255           6 :          DEALLOCATE (velocity)
     256             :       END IF
     257          26 :       IF (my_end) THEN
     258          20 :          CPWARN_IF(j /= natom, "BOX information missing in CRD file.")
     259             :       ELSE
     260           6 :          IF (j /= natom) &
     261             :             CALL cp_warn(__LOCATION__, &
     262             :                          "BOX information found in CRD file. They will be ignored. "// &
     263           6 :                          "Please provide the BOX information directly from the main CP2K input!")
     264             :       END IF
     265          26 :       CALL parser_release(parser)
     266             :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
     267          26 :                                         "PRINT%TOPOLOGY_INFO/CRD_INFO")
     268          26 :       CALL timestop(handle)
     269             : 
     270          78 :    END SUBROUTINE read_coordinate_crd
     271             : 
     272             : ! **************************************************************************************************
     273             : !> \brief Read AMBER topology file (.top) : At this level we parse only the
     274             : !>        connectivity info the .top file. ForceField information will be
     275             : !>        handled later
     276             : !>
     277             : !> \param filename ...
     278             : !> \param topology ...
     279             : !> \param para_env ...
     280             : !> \param subsys_section ...
     281             : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
     282             : ! **************************************************************************************************
     283          22 :    SUBROUTINE read_connectivity_amber(filename, topology, para_env, subsys_section)
     284             :       CHARACTER(LEN=*), INTENT(IN)                       :: filename
     285             :       TYPE(topology_parameters_type), INTENT(INOUT)      :: topology
     286             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     287             :       TYPE(section_vals_type), POINTER                   :: subsys_section
     288             : 
     289             :       CHARACTER(len=*), PARAMETER :: routineN = 'read_connectivity_amber'
     290             : 
     291             :       INTEGER                                            :: handle, iw
     292             :       TYPE(atom_info_type), POINTER                      :: atom_info
     293             :       TYPE(connectivity_info_type), POINTER              :: conn_info
     294             :       TYPE(cp_logger_type), POINTER                      :: logger
     295             : 
     296          22 :       NULLIFY (logger)
     297          22 :       CALL timeset(routineN, handle)
     298          22 :       logger => cp_get_default_logger()
     299             :       iw = cp_print_key_unit_nr(logger, subsys_section, "PRINT%TOPOLOGY_INFO/AMBER_INFO", &
     300          22 :                                 extension=".subsysLog")
     301             : 
     302          22 :       atom_info => topology%atom_info
     303          22 :       conn_info => topology%conn_info
     304             : 
     305             :       ! Read the Amber topology file
     306             :       CALL rdparm_amber_8(filename, iw, para_env, do_connectivity=.TRUE., do_forcefield=.FALSE., &
     307          22 :                           atom_info=atom_info, conn_info=conn_info)
     308             : 
     309             :       ! Molnames have been internally generated
     310          22 :       topology%molname_generated = .TRUE.
     311             : 
     312             :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
     313          22 :                                         "PRINT%TOPOLOGY_INFO/AMBER_INFO")
     314          22 :       CALL timestop(handle)
     315          22 :    END SUBROUTINE read_connectivity_amber
     316             : 
     317             : ! **************************************************************************************************
     318             : !> \brief  Access information form the AMBER topology file
     319             : !>         Notes on file structure:
     320             : !>
     321             : !>          NATOM        ! Total number of Atoms
     322             : !>          NTYPES       ! Total number of distinct atom types
     323             : !>          NBONH        ! Number of bonds containing hydrogens
     324             : !>          MBONA        ! Number of bonds not containing hydrogens
     325             : !>          NTHETH       ! Number of angles containing hydrogens
     326             : !>          MTHETA       ! Number of angles not containing hydrogens
     327             : !>          NPHIH        ! Number of dihedrals containing hydrogens
     328             : !>          MPHIA        ! Number of dihedrals not containing hydrogens
     329             : !>          NHPARM       !    currently NOT USED
     330             : !>          NPARM        !    set to 1 if LES is used
     331             : !>          NNB          !    number of excluded atoms
     332             : !>          NRES         ! Number of residues
     333             : !>          NBONA        !    MBONA  + number of constraint bonds     ( in v.8 NBONA=MBONA)
     334             : !>          NTHETA       !    MTHETA + number of constraint angles    ( in v.8 NBONA=MBONA)
     335             : !>          NPHIA        !    MPHIA  + number of constraint dihedrals ( in v.8 NBONA=MBONA)
     336             : !>          NUMBND       ! Number of unique bond types
     337             : !>          NUMANG       ! Number of unique angle types
     338             : !>          NPTRA        ! Number of unique dihedral types
     339             : !>          NATYP        ! Number of atom types in parameter file
     340             : !>          NPHB         ! Number of distinct 10-12 hydrogen bond pair types
     341             : !>          IFPERT       !    Variable not used in this converter...
     342             : !>          NBPER        !    Variable not used in this converter...
     343             : !>          NGPER        !    Variable not used in this converter...
     344             : !>          NDPER        !    Variable not used in this converter...
     345             : !>          MBPER        !    Variable not used in this converter...
     346             : !>          MGPER        !    Variable not used in this converter...
     347             : !>          MDPER        !    Variable not used in this converter...
     348             : !>          IFBOX        !    Variable not used in this converter...
     349             : !>          NMXRS        !    Variable not used in this converter...
     350             : !>          IFCAP        !    Variable not used in this converter...
     351             : !>          NUMEXTRA     !    Variable not used in this converter...
     352             : !>
     353             : !> \param filename ...
     354             : !> \param output_unit ...
     355             : !> \param para_env ...
     356             : !> \param do_connectivity ...
     357             : !> \param do_forcefield ...
     358             : !> \param atom_info ...
     359             : !> \param conn_info ...
     360             : !> \param amb_info ...
     361             : !> \param particle_set ...
     362             : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
     363             : ! **************************************************************************************************
     364          36 :    SUBROUTINE rdparm_amber_8(filename, output_unit, para_env, do_connectivity, &
     365             :                              do_forcefield, atom_info, conn_info, amb_info, particle_set)
     366             : 
     367             :       CHARACTER(LEN=*), INTENT(IN)                       :: filename
     368             :       INTEGER, INTENT(IN)                                :: output_unit
     369             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     370             :       LOGICAL, INTENT(IN)                                :: do_connectivity, do_forcefield
     371             :       TYPE(atom_info_type), OPTIONAL, POINTER            :: atom_info
     372             :       TYPE(connectivity_info_type), OPTIONAL, POINTER    :: conn_info
     373             :       TYPE(amber_info_type), OPTIONAL, POINTER           :: amb_info
     374             :       TYPE(particle_type), DIMENSION(:), OPTIONAL, &
     375             :          POINTER                                         :: particle_set
     376             : 
     377             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'rdparm_amber_8'
     378             : 
     379             :       CHARACTER(LEN=default_string_length)               :: input_format, section
     380             :       CHARACTER(LEN=default_string_length), &
     381          72 :          ALLOCATABLE, DIMENSION(:)                       :: isymbl, labres, strtmp_a
     382             :       INTEGER :: handle, handle2, i, ifbox, ifcap, ifpert, index_now, info(31), istart, mbona, &
     383             :          mbper, mdper, mgper, mphia, mtheta, natom, natom_prev, natyp, nbona, nbond_prev, nbonh, &
     384             :          nbper, ndper, ngper, nhparm, nmxrs, nnb, nparm, nphb, nphi_prev, nphia, nphih, nptra, &
     385             :          nres, nsize, ntheta, ntheta_prev, ntheth, ntypes, numang, numbnd, numextra, &
     386             :          unique_torsions
     387          36 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: iac, ib, ibh, icb, icbh, ico, icp, icph, &
     388          36 :                                                             ict, icth, ip, iph, ipres, it, ith, &
     389          36 :                                                             iwork, jb, jbh, jp, jph, jt, jth, kp, &
     390          36 :                                                             kph, kt, kth, lp, lph
     391          36 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: full_torsions
     392             :       LOGICAL                                            :: check, valid_format
     393          72 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: asol, bsol, cn1, cn2, phase, pk, pn, &
     394          36 :                                                             req, rk, teq, tk
     395             :       TYPE(cp_parser_type)                               :: parser
     396             : 
     397          36 :       CALL timeset(routineN, handle)
     398          36 :       IF (output_unit > 0) WRITE (output_unit, '(/,A)') " AMBER_INFO| Reading Amber Topology File: "// &
     399           3 :          TRIM(filename)
     400          36 :       CALL parser_create(parser, filename, para_env=para_env, parse_white_lines=.TRUE.)
     401          36 :       valid_format = check_amber_8_std(parser, output_unit)
     402          36 :       IF (valid_format) THEN
     403        1412 :          DO WHILE (get_section_parmtop(parser, section, input_format))
     404          36 :             SELECT CASE (TRIM(section))
     405             :             CASE ("TITLE")
     406             :                ! Who cares about the title?
     407          36 :                CYCLE
     408             :             CASE ("POINTERS")
     409          36 :                CALL rd_amber_section(parser, section, info, 31)
     410             :                ! Assign pointers to the corresponding labels
     411             :                ! just for convenience to have something more human readable
     412          36 :                natom = info(1)
     413          36 :                ntypes = info(2)
     414          36 :                nbonh = info(3)
     415          36 :                mbona = info(4)
     416          36 :                ntheth = info(5)
     417          36 :                mtheta = info(6)
     418          36 :                nphih = info(7)
     419          36 :                mphia = info(8)
     420          36 :                nhparm = info(9)
     421          36 :                nparm = info(10)
     422          36 :                nnb = info(11)
     423          36 :                nres = info(12)
     424          36 :                nbona = info(13)
     425          36 :                ntheta = info(14)
     426          36 :                nphia = info(15)
     427          36 :                numbnd = info(16)
     428          36 :                numang = info(17)
     429          36 :                nptra = info(18)
     430          36 :                natyp = info(19)
     431          36 :                nphb = info(20)
     432          36 :                ifpert = info(21)
     433          36 :                nbper = info(22)
     434          36 :                ngper = info(23)
     435          36 :                ndper = info(24)
     436          36 :                mbper = info(25)
     437          36 :                mgper = info(26)
     438          36 :                mdper = info(27)
     439          36 :                ifbox = info(28)
     440          36 :                nmxrs = info(29)
     441          36 :                ifcap = info(30)
     442          36 :                numextra = info(31)
     443             : 
     444             :                ! Print some info if requested
     445          36 :                IF (output_unit > 0) THEN
     446           3 :                   WRITE (output_unit, '(A,/)') " AMBER_INFO| Information from AMBER topology file:"
     447             :                   WRITE (output_unit, 1000) &
     448           3 :                      natom, ntypes, nbonh, mbona, ntheth, mtheta, nphih, &
     449           3 :                      mphia, nhparm, nparm, nnb, nres, nbona, ntheta, &
     450           3 :                      nphia, numbnd, numang, nptra, natyp, nphb, ifbox, &
     451           6 :                      nmxrs, ifcap, numextra
     452             :                END IF
     453             : 
     454             :                ! Allocate temporary arrays
     455          36 :                IF (do_connectivity) THEN
     456          22 :                   check = PRESENT(atom_info) .AND. PRESENT(conn_info)
     457          22 :                   CPASSERT(check)
     458          22 :                   natom_prev = 0
     459          22 :                   IF (ASSOCIATED(atom_info%id_molname)) natom_prev = SIZE(atom_info%id_molname)
     460             :                   ! Allocate for extracting connectivity infos
     461          66 :                   ALLOCATE (labres(nres))
     462          66 :                   ALLOCATE (ipres(nres))
     463             :                END IF
     464          36 :                IF (do_forcefield) THEN
     465             :                   ! Allocate for extracting forcefield infos
     466          42 :                   ALLOCATE (iac(natom))
     467          42 :                   ALLOCATE (ico(ntypes*ntypes))
     468          42 :                   ALLOCATE (rk(numbnd))
     469          28 :                   ALLOCATE (req(numbnd))
     470          42 :                   ALLOCATE (tk(numang))
     471          28 :                   ALLOCATE (teq(numang))
     472          40 :                   ALLOCATE (pk(nptra))
     473          26 :                   ALLOCATE (pn(nptra))
     474          26 :                   ALLOCATE (phase(nptra))
     475          42 :                   ALLOCATE (cn1(ntypes*(ntypes + 1)/2))
     476          28 :                   ALLOCATE (cn2(ntypes*(ntypes + 1)/2))
     477          28 :                   ALLOCATE (asol(ntypes*(ntypes + 1)/2))
     478          28 :                   ALLOCATE (bsol(ntypes*(ntypes + 1)/2))
     479             :                END IF
     480             :                ! Always Allocate
     481         108 :                ALLOCATE (ibh(nbonh))
     482          72 :                ALLOCATE (jbh(nbonh))
     483          72 :                ALLOCATE (icbh(nbonh))
     484         104 :                ALLOCATE (ib(nbona))
     485          68 :                ALLOCATE (jb(nbona))
     486          68 :                ALLOCATE (icb(nbona))
     487         108 :                ALLOCATE (ith(ntheth))
     488          72 :                ALLOCATE (jth(ntheth))
     489          72 :                ALLOCATE (kth(ntheth))
     490          72 :                ALLOCATE (icth(ntheth))
     491         104 :                ALLOCATE (it(ntheta))
     492          68 :                ALLOCATE (jt(ntheta))
     493          68 :                ALLOCATE (kt(ntheta))
     494          68 :                ALLOCATE (ict(ntheta))
     495         104 :                ALLOCATE (iph(nphih))
     496          68 :                ALLOCATE (jph(nphih))
     497          68 :                ALLOCATE (kph(nphih))
     498          68 :                ALLOCATE (lph(nphih))
     499          68 :                ALLOCATE (icph(nphih))
     500         104 :                ALLOCATE (ip(nphia))
     501          68 :                ALLOCATE (jp(nphia))
     502          68 :                ALLOCATE (kp(nphia))
     503          68 :                ALLOCATE (lp(nphia))
     504          68 :                ALLOCATE (icp(nphia))
     505             :             CASE ("ATOM_NAME")
     506             :                ! Atom names are just ignored according the CP2K philosophy
     507          36 :                CYCLE
     508             :             CASE ("AMBER_ATOM_TYPE")
     509          36 :                IF (.NOT. do_connectivity) CYCLE
     510          22 :                CALL reallocate(atom_info%id_atmname, 1, natom_prev + natom)
     511          66 :                ALLOCATE (strtmp_a(natom))
     512          22 :                CALL rd_amber_section(parser, section, strtmp_a, natom)
     513       78860 :                DO i = 1, natom
     514       78860 :                   atom_info%id_atmname(natom_prev + i) = str2id(strtmp_a(i))
     515             :                END DO
     516          22 :                DEALLOCATE (strtmp_a)
     517             :             CASE ("CHARGE")
     518          36 :                IF (.NOT. do_connectivity) CYCLE
     519          22 :                CALL reallocate(atom_info%atm_charge, 1, natom_prev + natom)
     520          22 :                CALL rd_amber_section(parser, section, atom_info%atm_charge(natom_prev + 1:), natom)
     521             :                ! Convert charges into atomic units
     522       78860 :                atom_info%atm_charge(natom_prev + 1:) = atom_info%atm_charge(natom_prev + 1:)/amber_conv_charge
     523             :             CASE ("MASS")
     524          36 :                IF (.NOT. do_connectivity) CYCLE
     525          22 :                CALL reallocate(atom_info%atm_mass, 1, natom_prev + natom)
     526          22 :                CALL rd_amber_section(parser, section, atom_info%atm_mass(natom_prev + 1:), natom)
     527             :             CASE ("RESIDUE_LABEL")
     528          36 :                IF (.NOT. do_connectivity) CYCLE
     529          22 :                CALL reallocate(atom_info%id_resname, 1, natom_prev + natom)
     530          22 :                CALL rd_amber_section(parser, section, labres, nres)
     531             :             CASE ("RESIDUE_POINTER")
     532          36 :                IF (.NOT. do_connectivity) CYCLE
     533          22 :                CALL reallocate(atom_info%resid, 1, natom_prev + natom)
     534          22 :                CALL rd_amber_section(parser, section, ipres, nres)
     535             :             CASE ("ATOM_TYPE_INDEX")
     536          36 :                IF (.NOT. do_forcefield) CYCLE
     537          14 :                CALL rd_amber_section(parser, section, iac, natom)
     538             :             CASE ("NONBONDED_PARM_INDEX")
     539          36 :                IF (.NOT. do_forcefield) CYCLE
     540          14 :                CALL rd_amber_section(parser, section, ico, ntypes**2)
     541             :             CASE ("BOND_FORCE_CONSTANT")
     542          36 :                IF (.NOT. do_forcefield) CYCLE
     543          14 :                CALL rd_amber_section(parser, section, rk, numbnd)
     544             :             CASE ("BOND_EQUIL_VALUE")
     545          36 :                IF (.NOT. do_forcefield) CYCLE
     546          14 :                CALL rd_amber_section(parser, section, req, numbnd)
     547             :             CASE ("ANGLE_FORCE_CONSTANT")
     548          36 :                IF (.NOT. do_forcefield) CYCLE
     549          14 :                CALL rd_amber_section(parser, section, tk, numang)
     550             :             CASE ("ANGLE_EQUIL_VALUE")
     551          36 :                IF (.NOT. do_forcefield) CYCLE
     552          14 :                CALL rd_amber_section(parser, section, teq, numang)
     553             :             CASE ("DIHEDRAL_FORCE_CONSTANT")
     554          36 :                IF (.NOT. do_forcefield) CYCLE
     555          14 :                CALL rd_amber_section(parser, section, pk, nptra)
     556          14 :                IF (nptra <= 0) CYCLE
     557             :                ! Save raw values
     558          12 :                IF (ASSOCIATED(amb_info%raw_torsion_k)) DEALLOCATE (amb_info%raw_torsion_k)
     559         358 :                ALLOCATE (amb_info%raw_torsion_k(nptra), source=pk)
     560             :             CASE ("DIHEDRAL_PERIODICITY")
     561          36 :                IF (.NOT. do_forcefield) CYCLE
     562          14 :                CALL rd_amber_section(parser, section, pn, nptra)
     563          14 :                IF (nptra <= 0) CYCLE
     564             :                ! Save raw values
     565          12 :                IF (ASSOCIATED(amb_info%raw_torsion_m)) DEALLOCATE (amb_info%raw_torsion_m)
     566         358 :                ALLOCATE (amb_info%raw_torsion_m(nptra), source=pn)
     567             :             CASE ("DIHEDRAL_PHASE")
     568          36 :                IF (.NOT. do_forcefield) CYCLE
     569          14 :                CALL rd_amber_section(parser, section, phase, nptra)
     570          14 :                IF (nptra <= 0) CYCLE
     571             :                ! Save raw values
     572          12 :                IF (ASSOCIATED(amb_info%raw_torsion_phi0)) DEALLOCATE (amb_info%raw_torsion_phi0)
     573         358 :                ALLOCATE (amb_info%raw_torsion_phi0(nptra), source=phase)
     574             :             CASE ("LENNARD_JONES_ACOEF")
     575          36 :                IF (.NOT. do_forcefield) CYCLE
     576          14 :                CALL rd_amber_section(parser, section, cn1, ntypes*(ntypes + 1)/2)
     577             :             CASE ("LENNARD_JONES_BCOEF")
     578          36 :                IF (.NOT. do_forcefield) CYCLE
     579          14 :                CALL rd_amber_section(parser, section, cn2, ntypes*(ntypes + 1)/2)
     580             :             CASE ("HBOND_ACOEF")
     581          36 :                IF (.NOT. do_forcefield) CYCLE
     582          14 :                CALL rd_amber_section(parser, section, asol, nphb)
     583             :             CASE ("HBOND_BCOEF")
     584          36 :                IF (.NOT. do_forcefield) CYCLE
     585          14 :                CALL rd_amber_section(parser, section, bsol, nphb)
     586             :             CASE ("BONDS_INC_HYDROGEN")
     587             :                ! We always need to parse this information both for connectivity and forcefields
     588          36 :                CALL rd_amber_section(parser, section, ibh, jbh, icbh, nbonh)
     589             :                ! Conver to an atomic index
     590      100028 :                ibh(:) = ibh(:)/3 + 1
     591      100028 :                jbh(:) = jbh(:)/3 + 1
     592             :             CASE ("BONDS_WITHOUT_HYDROGEN")
     593             :                ! We always need to parse this information both for connectivity and forcefields
     594          36 :                CALL rd_amber_section(parser, section, ib, jb, icb, nbona)
     595             :                ! Conver to an atomic index
     596       14022 :                ib(:) = ib(:)/3 + 1
     597       14022 :                jb(:) = jb(:)/3 + 1
     598             :             CASE ("ANGLES_INC_HYDROGEN")
     599             :                ! We always need to parse this information both for connectivity and forcefields
     600          36 :                CALL rd_amber_section(parser, section, ith, jth, kth, icth, ntheth)
     601             :                ! Conver to an atomic index
     602       72486 :                ith(:) = ith(:)/3 + 1
     603       72486 :                jth(:) = jth(:)/3 + 1
     604       72486 :                kth(:) = kth(:)/3 + 1
     605             :             CASE ("ANGLES_WITHOUT_HYDROGEN")
     606             :                ! We always need to parse this information both for connectivity and forcefields
     607          36 :                CALL rd_amber_section(parser, section, it, jt, kt, ict, ntheta)
     608             :                ! Conver to an atomic index
     609       18954 :                it(:) = it(:)/3 + 1
     610       18954 :                jt(:) = jt(:)/3 + 1
     611       18954 :                kt(:) = kt(:)/3 + 1
     612             :             CASE ("DIHEDRALS_INC_HYDROGEN")
     613             :                ! We always need to parse this information both for connectivity and forcefields
     614          36 :                CALL rd_amber_section(parser, section, iph, jph, kph, lph, icph, nphih)
     615             :                ! Conver to an atomic index
     616       56580 :                iph(:) = iph(:)/3 + 1
     617       56580 :                jph(:) = jph(:)/3 + 1
     618       56580 :                kph(:) = ABS(kph(:))/3 + 1
     619       56580 :                lph(:) = ABS(lph(:))/3 + 1
     620             :             CASE ("DIHEDRALS_WITHOUT_HYDROGEN")
     621             :                ! We always need to parse this information both for connectivity and forcefields
     622          36 :                CALL rd_amber_section(parser, section, ip, jp, kp, lp, icp, nphia)
     623             :                ! Conver to an atomic index
     624       45272 :                ip(:) = ip(:)/3 + 1
     625       45272 :                jp(:) = jp(:)/3 + 1
     626       45272 :                kp(:) = ABS(kp(:))/3 + 1
     627       46662 :                lp(:) = ABS(lp(:))/3 + 1
     628             :             CASE DEFAULT
     629             :                ! Just Ignore other sections...
     630             :             END SELECT
     631             :          END DO
     632             :          ! Save raw torsion info: atom indices and dihedral index
     633          36 :          IF (do_forcefield .AND. (nphih + nphia > 0)) THEN
     634          12 :             IF (ASSOCIATED(amb_info%raw_torsion_id)) DEALLOCATE (amb_info%raw_torsion_id)
     635          36 :             ALLOCATE (amb_info%raw_torsion_id(5, nphih + nphia))
     636       28078 :             DO i = 1, nphih
     637       28066 :                amb_info%raw_torsion_id(1, i) = iph(i)
     638       28066 :                amb_info%raw_torsion_id(2, i) = jph(i)
     639       28066 :                amb_info%raw_torsion_id(3, i) = kph(i)
     640       28066 :                amb_info%raw_torsion_id(4, i) = lph(i)
     641       28078 :                amb_info%raw_torsion_id(5, i) = icph(i)
     642             :             END DO
     643       22334 :             DO i = 1, nphia
     644       22322 :                amb_info%raw_torsion_id(1, nphih + i) = ip(i)
     645       22322 :                amb_info%raw_torsion_id(2, nphih + i) = jp(i)
     646       22322 :                amb_info%raw_torsion_id(3, nphih + i) = kp(i)
     647       22322 :                amb_info%raw_torsion_id(4, nphih + i) = lp(i)
     648       22334 :                amb_info%raw_torsion_id(5, nphih + i) = icp(i)
     649             :             END DO
     650             :          END IF
     651             :       END IF
     652             : 
     653             :       ! Extracts connectivity info from the AMBER topology file
     654          36 :       IF (do_connectivity) THEN
     655          22 :          CALL timeset(TRIM(routineN)//"_connectivity", handle2)
     656             :          ! ----------------------------------------------------------
     657             :          ! Conform Amber Names with CHARMM convention (kind<->charge)
     658             :          ! ----------------------------------------------------------
     659          66 :          ALLOCATE (isymbl(natom))
     660          66 :          ALLOCATE (iwork(natom))
     661             : 
     662       78860 :          DO i = 1, SIZE(isymbl)
     663       78860 :             isymbl(i) = id2str(atom_info%id_atmname(natom_prev + i))
     664             :          END DO
     665             : 
     666             :          ! Sort atom names + charges and identify unique types
     667          22 :          CALL sort(isymbl, natom, iwork)
     668             : 
     669          22 :          istart = 1
     670       78838 :          DO i = 2, natom
     671       78838 :             IF (TRIM(isymbl(i)) /= TRIM(isymbl(istart))) THEN
     672         228 :                CALL conform_atom_type_low(isymbl, iwork, i, istart, atom_info%atm_charge(natom_prev + 1:))
     673         228 :                istart = i
     674             :             END IF
     675             :          END DO
     676          22 :          CALL conform_atom_type_low(isymbl, iwork, i, istart, atom_info%atm_charge(natom_prev + 1:))
     677             : 
     678             :          ! Copy back the modified and conformed atom types
     679       78860 :          DO i = 1, natom
     680       78860 :             atom_info%id_atmname(natom_prev + iwork(i)) = str2id(s2s(isymbl(i)))
     681             :          END DO
     682             : 
     683             :          ! -----------------------------------------------------------
     684             :          ! Fill residue_name and residue_id information before exiting
     685             :          ! -----------------------------------------------------------
     686       22730 :          DO i = 1, nres - 1
     687      123776 :             atom_info%id_resname(natom_prev + ipres(i):natom_prev + ipres(i + 1)) = str2id(s2s(labres(i)))
     688      123798 :             atom_info%resid(natom_prev + ipres(i):natom_prev + ipres(i + 1)) = i
     689             :          END DO
     690         500 :          atom_info%id_resname(natom_prev + ipres(i):natom_prev + natom) = str2id(s2s(labres(i)))
     691         500 :          atom_info%resid(natom_prev + ipres(i):natom_prev + natom) = i
     692             : 
     693             :          ! Deallocate when extracting connectivity infos
     694          22 :          DEALLOCATE (iwork)
     695          22 :          DEALLOCATE (isymbl)
     696          22 :          DEALLOCATE (labres)
     697          22 :          DEALLOCATE (ipres)
     698             : 
     699             :          ! ----------------------------------------------------------
     700             :          ! Copy connectivity
     701             :          ! ----------------------------------------------------------
     702             :          ! BONDS
     703          22 :          nbond_prev = 0
     704          22 :          IF (ASSOCIATED(conn_info%bond_a)) nbond_prev = SIZE(conn_info%bond_a)
     705             : 
     706          22 :          CALL reallocate(conn_info%bond_a, 1, nbond_prev + nbonh + nbona)
     707          22 :          CALL reallocate(conn_info%bond_b, 1, nbond_prev + nbonh + nbona)
     708       50078 :          DO i = 1, nbonh
     709       50056 :             index_now = nbond_prev + i
     710       50056 :             conn_info%bond_a(index_now) = natom_prev + ibh(i)
     711       50078 :             conn_info%bond_b(index_now) = natom_prev + jbh(i)
     712             :          END DO
     713        7144 :          DO i = 1, nbona
     714        7122 :             index_now = nbond_prev + i + nbonh
     715        7122 :             conn_info%bond_a(index_now) = natom_prev + ib(i)
     716        7144 :             conn_info%bond_b(index_now) = natom_prev + jb(i)
     717             :          END DO
     718             : 
     719             :          ! ANGLES
     720          22 :          ntheta_prev = 0
     721          22 :          IF (ASSOCIATED(conn_info%theta_a)) ntheta_prev = SIZE(conn_info%theta_a)
     722             : 
     723          22 :          CALL reallocate(conn_info%theta_a, 1, ntheta_prev + ntheth + ntheta)
     724          22 :          CALL reallocate(conn_info%theta_b, 1, ntheta_prev + ntheth + ntheta)
     725          22 :          CALL reallocate(conn_info%theta_c, 1, ntheta_prev + ntheth + ntheta)
     726       36368 :          DO i = 1, ntheth
     727       36346 :             index_now = ntheta_prev + i
     728       36346 :             conn_info%theta_a(index_now) = natom_prev + ith(i)
     729       36346 :             conn_info%theta_b(index_now) = natom_prev + jth(i)
     730       36368 :             conn_info%theta_c(index_now) = natom_prev + kth(i)
     731             :          END DO
     732        9672 :          DO i = 1, ntheta
     733        9650 :             index_now = ntheta_prev + i + ntheth
     734        9650 :             conn_info%theta_a(index_now) = natom_prev + it(i)
     735        9650 :             conn_info%theta_b(index_now) = natom_prev + jt(i)
     736        9672 :             conn_info%theta_c(index_now) = natom_prev + kt(i)
     737             :          END DO
     738             : 
     739             :          ! TORSIONS
     740             :          ! For torsions we need to find out the unique torsions
     741             :          ! defined in the amber parmtop
     742          22 :          nphi_prev = 0
     743          22 :          IF (ASSOCIATED(conn_info%phi_a)) nphi_prev = SIZE(conn_info%phi_a)
     744             : 
     745          22 :          CALL reallocate(conn_info%phi_a, 1, nphi_prev + nphih + nphia)
     746          22 :          CALL reallocate(conn_info%phi_b, 1, nphi_prev + nphih + nphia)
     747          22 :          CALL reallocate(conn_info%phi_c, 1, nphi_prev + nphih + nphia)
     748          22 :          CALL reallocate(conn_info%phi_d, 1, nphi_prev + nphih + nphia)
     749             : 
     750          22 :          IF (nphih + nphia /= 0) THEN
     751          60 :             ALLOCATE (full_torsions(4, nphih + nphia))
     752          60 :             ALLOCATE (iwork(nphih + nphia))
     753             : 
     754       28498 :             DO i = 1, nphih
     755       28478 :                full_torsions(1, i) = iph(i)
     756       28478 :                full_torsions(2, i) = jph(i)
     757       28478 :                full_torsions(3, i) = kph(i)
     758       28498 :                full_torsions(4, i) = lph(i)
     759             :             END DO
     760       22934 :             DO i = 1, nphia
     761       22914 :                full_torsions(1, nphih + i) = ip(i)
     762       22914 :                full_torsions(2, nphih + i) = jp(i)
     763       22914 :                full_torsions(3, nphih + i) = kp(i)
     764       22934 :                full_torsions(4, nphih + i) = lp(i)
     765             :             END DO
     766          20 :             CALL sort(full_torsions, 1, nphih + nphia, 1, 4, iwork)
     767             : 
     768          20 :             unique_torsions = nphi_prev + 1
     769          20 :             conn_info%phi_a(unique_torsions) = natom_prev + full_torsions(1, 1)
     770          20 :             conn_info%phi_b(unique_torsions) = natom_prev + full_torsions(2, 1)
     771          20 :             conn_info%phi_c(unique_torsions) = natom_prev + full_torsions(3, 1)
     772          20 :             conn_info%phi_d(unique_torsions) = natom_prev + full_torsions(4, 1)
     773       51392 :             DO i = 2, nphih + nphia
     774             :                IF ((full_torsions(1, i) /= full_torsions(1, i - 1)) .OR. &
     775             :                    (full_torsions(2, i) /= full_torsions(2, i - 1)) .OR. &
     776       51372 :                    (full_torsions(3, i) /= full_torsions(3, i - 1)) .OR. &
     777          20 :                    (full_torsions(4, i) /= full_torsions(4, i - 1))) THEN
     778       37586 :                   unique_torsions = unique_torsions + 1
     779       37586 :                   conn_info%phi_a(unique_torsions) = natom_prev + full_torsions(1, i)
     780       37586 :                   conn_info%phi_b(unique_torsions) = natom_prev + full_torsions(2, i)
     781       37586 :                   conn_info%phi_c(unique_torsions) = natom_prev + full_torsions(3, i)
     782       37586 :                   conn_info%phi_d(unique_torsions) = natom_prev + full_torsions(4, i)
     783             :                END IF
     784             :             END DO
     785          20 :             CALL reallocate(conn_info%phi_a, 1, unique_torsions)
     786          20 :             CALL reallocate(conn_info%phi_b, 1, unique_torsions)
     787          20 :             CALL reallocate(conn_info%phi_c, 1, unique_torsions)
     788          20 :             CALL reallocate(conn_info%phi_d, 1, unique_torsions)
     789             : 
     790          20 :             DEALLOCATE (full_torsions)
     791          20 :             DEALLOCATE (iwork)
     792             :          END IF
     793             :          ! IMPROPERS
     794          22 :          CALL reallocate(conn_info%impr_a, 1, 0)
     795          22 :          CALL reallocate(conn_info%impr_b, 1, 0)
     796          22 :          CALL reallocate(conn_info%impr_c, 1, 0)
     797          22 :          CALL reallocate(conn_info%impr_d, 1, 0)
     798             : 
     799             :          ! ----------------------------------------------------------
     800             :          ! Generate molecule names
     801             :          ! ----------------------------------------------------------
     802          22 :          CALL reallocate(atom_info%id_molname, 1, natom_prev + natom)
     803       78860 :          atom_info%id_molname(natom_prev + 1:natom_prev + natom) = str2id(s2s("__UNDEF__"))
     804             :          CALL topology_generate_molname(conn_info, natom, natom_prev, nbond_prev, &
     805          22 :                                         atom_info%id_molname(natom_prev + 1:natom_prev + natom))
     806          44 :          CALL timestop(handle2)
     807             :       END IF
     808             : 
     809             :       ! Extracts force fields info from the AMBER topology file
     810          36 :       IF (do_forcefield) THEN
     811          14 :          CALL timeset(TRIM(routineN)//"_forcefield", handle2)
     812             :          ! ----------------------------------------------------------
     813             :          ! Force Fields informations related to bonds
     814             :          ! ----------------------------------------------------------
     815          14 :          CALL reallocate(amb_info%bond_a, 1, buffer_size)
     816          14 :          CALL reallocate(amb_info%bond_b, 1, buffer_size)
     817          14 :          CALL reallocate(amb_info%bond_k, 1, buffer_size)
     818          14 :          CALL reallocate(amb_info%bond_r0, 1, buffer_size)
     819          14 :          nsize = 0
     820             :          ! Bonds containing hydrogens
     821             :          CALL post_process_bonds_info(amb_info%bond_a, amb_info%bond_b, &
     822             :                                       amb_info%bond_k, amb_info%bond_r0, particle_set, nsize, &
     823          14 :                                       nbonh, ibh, jbh, icbh, rk, req)
     824             :          ! Bonds non-containing hydrogens
     825             :          CALL post_process_bonds_info(amb_info%bond_a, amb_info%bond_b, &
     826             :                                       amb_info%bond_k, amb_info%bond_r0, particle_set, nsize, &
     827          14 :                                       nbona, ib, jb, icb, rk, req)
     828             :          ! Shrink arrays size to the minimal request
     829          14 :          CALL reallocate(amb_info%bond_a, 1, nsize)
     830          14 :          CALL reallocate(amb_info%bond_b, 1, nsize)
     831          14 :          CALL reallocate(amb_info%bond_k, 1, nsize)
     832          14 :          CALL reallocate(amb_info%bond_r0, 1, nsize)
     833             : 
     834             :          ! ----------------------------------------------------------
     835             :          ! Force Fields informations related to bends
     836             :          ! ----------------------------------------------------------
     837          14 :          CALL reallocate(amb_info%bend_a, 1, buffer_size)
     838          14 :          CALL reallocate(amb_info%bend_b, 1, buffer_size)
     839          14 :          CALL reallocate(amb_info%bend_c, 1, buffer_size)
     840          14 :          CALL reallocate(amb_info%bend_k, 1, buffer_size)
     841          14 :          CALL reallocate(amb_info%bend_theta0, 1, buffer_size)
     842          14 :          nsize = 0
     843             :          ! Bends containing hydrogens
     844             :          CALL post_process_bends_info(amb_info%bend_a, amb_info%bend_b, &
     845             :                                       amb_info%bend_c, amb_info%bend_k, amb_info%bend_theta0, &
     846          14 :                                       particle_set, nsize, ntheth, ith, jth, kth, icth, tk, teq)
     847             :          ! Bends non-containing hydrogens
     848             :          CALL post_process_bends_info(amb_info%bend_a, amb_info%bend_b, &
     849             :                                       amb_info%bend_c, amb_info%bend_k, amb_info%bend_theta0, &
     850          14 :                                       particle_set, nsize, ntheta, it, jt, kt, ict, tk, teq)
     851             :          ! Shrink arrays size to the minimal request
     852          14 :          CALL reallocate(amb_info%bend_a, 1, nsize)
     853          14 :          CALL reallocate(amb_info%bend_b, 1, nsize)
     854          14 :          CALL reallocate(amb_info%bend_c, 1, nsize)
     855          14 :          CALL reallocate(amb_info%bend_k, 1, nsize)
     856          14 :          CALL reallocate(amb_info%bend_theta0, 1, nsize)
     857             : 
     858             :          ! ----------------------------------------------------------
     859             :          ! Force Fields informations related to torsions
     860             :          ! in amb_info%phi0 we store PHI0
     861             :          ! ----------------------------------------------------------
     862             : 
     863          14 :          CALL reallocate(amb_info%torsion_a, 1, buffer_size)
     864          14 :          CALL reallocate(amb_info%torsion_b, 1, buffer_size)
     865          14 :          CALL reallocate(amb_info%torsion_c, 1, buffer_size)
     866          14 :          CALL reallocate(amb_info%torsion_d, 1, buffer_size)
     867          14 :          CALL reallocate(amb_info%torsion_k, 1, buffer_size)
     868          14 :          CALL reallocate(amb_info%torsion_m, 1, buffer_size)
     869          14 :          CALL reallocate(amb_info%torsion_phi0, 1, buffer_size)
     870          14 :          nsize = 0
     871             :          ! Torsions containing hydrogens
     872             :          CALL post_process_torsions_info(amb_info%torsion_a, amb_info%torsion_b, &
     873             :                                          amb_info%torsion_c, amb_info%torsion_d, amb_info%torsion_k, &
     874             :                                          amb_info%torsion_m, amb_info%torsion_phi0, particle_set, nsize, &
     875          14 :                                          nphih, iph, jph, kph, lph, icph, pk, pn, phase)
     876             :          ! Torsions non-containing hydrogens
     877             :          CALL post_process_torsions_info(amb_info%torsion_a, amb_info%torsion_b, &
     878             :                                          amb_info%torsion_c, amb_info%torsion_d, amb_info%torsion_k, &
     879             :                                          amb_info%torsion_m, amb_info%torsion_phi0, particle_set, nsize, &
     880          14 :                                          nphia, ip, jp, kp, lp, icp, pk, pn, phase)
     881             :          ! Shrink arrays size to the minimal request
     882          14 :          CALL reallocate(amb_info%torsion_a, 1, nsize)
     883          14 :          CALL reallocate(amb_info%torsion_b, 1, nsize)
     884          14 :          CALL reallocate(amb_info%torsion_c, 1, nsize)
     885          14 :          CALL reallocate(amb_info%torsion_d, 1, nsize)
     886          14 :          CALL reallocate(amb_info%torsion_k, 1, nsize)
     887          14 :          CALL reallocate(amb_info%torsion_m, 1, nsize)
     888          14 :          CALL reallocate(amb_info%torsion_phi0, 1, nsize)
     889             : 
     890             :          ! Sort dihedral metadata for faster lookup
     891          14 :          IF (nphih + nphia /= 0) THEN
     892          36 :             ALLOCATE (iwork(nphih + nphia))
     893          12 :             CALL sort(amb_info%raw_torsion_id, 1, nphih + nphia, 1, 5, iwork)
     894          12 :             DEALLOCATE (iwork)
     895             :          END IF
     896             : 
     897             :          ! ----------------------------------------------------------
     898             :          ! Post process of LJ parameters
     899             :          ! ----------------------------------------------------------
     900          14 :          CALL reallocate(amb_info%nonbond_a, 1, buffer_size)
     901          14 :          CALL reallocate(amb_info%nonbond_eps, 1, buffer_size)
     902          14 :          CALL reallocate(amb_info%nonbond_rmin2, 1, buffer_size)
     903             : 
     904          14 :          nsize = 0
     905             :          CALL post_process_LJ_info(amb_info%nonbond_a, amb_info%nonbond_eps, &
     906             :                                    amb_info%nonbond_rmin2, particle_set, ntypes, nsize, iac, ico, &
     907          14 :                                    cn1, cn2, natom)
     908             : 
     909             :          ! Shrink arrays size to the minimal request
     910          14 :          CALL reallocate(amb_info%nonbond_a, 1, nsize)
     911          14 :          CALL reallocate(amb_info%nonbond_eps, 1, nsize)
     912          14 :          CALL reallocate(amb_info%nonbond_rmin2, 1, nsize)
     913             : 
     914             :          ! Deallocate at the end of the dirty job
     915          14 :          DEALLOCATE (iac)
     916          14 :          DEALLOCATE (ico)
     917          14 :          DEALLOCATE (rk)
     918          14 :          DEALLOCATE (req)
     919          14 :          DEALLOCATE (tk)
     920          14 :          DEALLOCATE (teq)
     921          14 :          DEALLOCATE (pk)
     922          14 :          DEALLOCATE (pn)
     923          14 :          DEALLOCATE (phase)
     924          14 :          DEALLOCATE (cn1)
     925          14 :          DEALLOCATE (cn2)
     926          14 :          DEALLOCATE (asol)
     927          14 :          DEALLOCATE (bsol)
     928          14 :          CALL timestop(handle2)
     929             :       END IF
     930             :       ! Always Deallocate
     931          36 :       DEALLOCATE (ibh)
     932          36 :       DEALLOCATE (jbh)
     933          36 :       DEALLOCATE (icbh)
     934          36 :       DEALLOCATE (ib)
     935          36 :       DEALLOCATE (jb)
     936          36 :       DEALLOCATE (icb)
     937          36 :       DEALLOCATE (ith)
     938          36 :       DEALLOCATE (jth)
     939          36 :       DEALLOCATE (kth)
     940          36 :       DEALLOCATE (icth)
     941          36 :       DEALLOCATE (it)
     942          36 :       DEALLOCATE (jt)
     943          36 :       DEALLOCATE (kt)
     944          36 :       DEALLOCATE (ict)
     945          36 :       DEALLOCATE (iph)
     946          36 :       DEALLOCATE (jph)
     947          36 :       DEALLOCATE (kph)
     948          36 :       DEALLOCATE (lph)
     949          36 :       DEALLOCATE (icph)
     950          36 :       DEALLOCATE (ip)
     951          36 :       DEALLOCATE (jp)
     952          36 :       DEALLOCATE (kp)
     953          36 :       DEALLOCATE (lp)
     954          36 :       DEALLOCATE (icp)
     955          36 :       CALL parser_release(parser)
     956          36 :       CALL timestop(handle)
     957          36 :       RETURN
     958             :       ! Output info Format
     959             : 1000  FORMAT(T2, &
     960             :              /' NATOM  = ', i7, ' NTYPES = ', i7, ' NBONH = ', i7, ' MBONA  = ', i7, &
     961             :              /' NTHETH = ', i7, ' MTHETA = ', i7, ' NPHIH = ', i7, ' MPHIA  = ', i7, &
     962             :              /' NHPARM = ', i7, ' NPARM  = ', i7, ' NNB   = ', i7, ' NRES   = ', i7, &
     963             :              /' NBONA  = ', i7, ' NTHETA = ', i7, ' NPHIA = ', i7, ' NUMBND = ', i7, &
     964             :              /' NUMANG = ', i7, ' NPTRA  = ', i7, ' NATYP = ', i7, ' NPHB   = ', i7, &
     965             :              /' IFBOX  = ', i7, ' NMXRS  = ', i7, ' IFCAP = ', i7, ' NEXTRA = ', i7,/)
     966         144 :    END SUBROUTINE rdparm_amber_8
     967             : 
     968             : ! **************************************************************************************************
     969             : !> \brief Low level routine to identify and rename unique atom types
     970             : !> \param isymbl ...
     971             : !> \param iwork ...
     972             : !> \param i ...
     973             : !> \param istart ...
     974             : !> \param charges ...
     975             : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
     976             : ! **************************************************************************************************
     977         250 :    SUBROUTINE conform_atom_type_low(isymbl, iwork, i, istart, charges)
     978             :       CHARACTER(LEN=default_string_length), DIMENSION(:) :: isymbl
     979             :       INTEGER, DIMENSION(:)                              :: iwork
     980             :       INTEGER, INTENT(IN)                                :: i
     981             :       INTEGER, INTENT(INOUT)                             :: istart
     982             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: charges
     983             : 
     984             :       CHARACTER(len=*), PARAMETER :: routineN = 'conform_atom_type_low'
     985             : 
     986             :       INTEGER                                            :: counter, gind, handle, iend, ind, isize, &
     987             :                                                             j, k, kend, kstart
     988         250 :       INTEGER, DIMENSION(:), POINTER                     :: cindx, lindx
     989             :       REAL(KIND=dp)                                      :: ctmp
     990         250 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: cwork
     991             : 
     992         250 :       CALL timeset(routineN, handle)
     993         250 :       iend = i - 1
     994         250 :       isize = iend - istart + 1
     995         750 :       ALLOCATE (cwork(isize))
     996         750 :       ALLOCATE (lindx(isize))
     997         500 :       ALLOCATE (cindx(isize))
     998         250 :       ind = 0
     999       79088 :       DO k = istart, iend
    1000       78838 :          ind = ind + 1
    1001       78838 :          cwork(ind) = charges(iwork(k))
    1002       79088 :          lindx(ind) = k
    1003             :       END DO
    1004         250 :       CALL sort(cwork, isize, cindx)
    1005             : 
    1006         250 :       ctmp = cwork(1)
    1007         250 :       counter = 1
    1008       78838 :       DO k = 2, isize
    1009       78838 :          IF (cwork(k) /= ctmp) THEN
    1010        1408 :             counter = counter + 1
    1011        1408 :             ctmp = cwork(k)
    1012             :          END IF
    1013             :       END DO
    1014         250 :       IF (counter /= 1) THEN
    1015         148 :          counter = 1
    1016         148 :          kstart = 1
    1017         148 :          ctmp = cwork(1)
    1018       12762 :          DO k = 2, isize
    1019       12762 :             IF (cwork(k) /= ctmp) THEN
    1020             :                kend = k - 1
    1021       12348 :                DO j = kstart, kend
    1022       10940 :                   gind = lindx(cindx(j))
    1023       12348 :                   isymbl(gind) = TRIM(isymbl(gind))//ADJUSTL(cp_to_string(counter))
    1024             :                END DO
    1025        1408 :                counter = counter + 1
    1026        1408 :                ctmp = cwork(k)
    1027        1408 :                kstart = k
    1028             :             END IF
    1029             :          END DO
    1030             :          kend = k - 1
    1031        1970 :          DO j = kstart, kend
    1032        1822 :             gind = lindx(cindx(j))
    1033        1970 :             isymbl(gind) = TRIM(isymbl(gind))//ADJUSTL(cp_to_string(counter))
    1034             :          END DO
    1035             :       END IF
    1036         250 :       DEALLOCATE (cwork)
    1037         250 :       DEALLOCATE (lindx)
    1038         250 :       DEALLOCATE (cindx)
    1039         250 :       CALL timestop(handle)
    1040         250 :    END SUBROUTINE conform_atom_type_low
    1041             : 
    1042             : ! **************************************************************************************************
    1043             : !> \brief Set of Low level subroutines reading section for parmtop
    1044             : !>        reading 1 array of integers of length dim
    1045             : !> \param parser ...
    1046             : !> \param section ...
    1047             : !> \param array1 ...
    1048             : !> \param dim ...
    1049             : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1050             : ! **************************************************************************************************
    1051          86 :    SUBROUTINE rd_amber_section_i1(parser, section, array1, dim)
    1052             :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1053             :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: section
    1054             :       INTEGER, DIMENSION(:)                              :: array1
    1055             :       INTEGER, INTENT(IN)                                :: dim
    1056             : 
    1057             :       INTEGER                                            :: i
    1058             :       LOGICAL                                            :: my_end
    1059             : 
    1060          86 :       CALL parser_get_next_line(parser, 1, at_end=my_end)
    1061          86 :       i = 1
    1062      104356 :       DO WHILE ((i <= dim) .AND. (.NOT. my_end))
    1063      104270 :          IF (parser_test_next_token(parser) == "EOL") &
    1064      114666 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1065      104270 :          IF (my_end) EXIT
    1066      104270 :          CALL parser_get_object(parser, array1(i))
    1067      104270 :          i = i + 1
    1068             :       END DO
    1069             :       ! Trigger end of file aborting
    1070          86 :       IF (my_end .AND. (i <= dim)) &
    1071             :          CALL cp_abort(__LOCATION__, &
    1072           0 :                        "End of file while reading section "//TRIM(section)//" in amber topology file!")
    1073          86 :    END SUBROUTINE rd_amber_section_i1
    1074             : 
    1075             : ! **************************************************************************************************
    1076             : !> \brief Set of Low level subroutines reading section for parmtop
    1077             : !>        reading 3 arrays of integers of length dim
    1078             : !> \param parser ...
    1079             : !> \param section ...
    1080             : !> \param array1 ...
    1081             : !> \param array2 ...
    1082             : !> \param array3 ...
    1083             : !> \param dim ...
    1084             : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1085             : ! **************************************************************************************************
    1086          72 :    SUBROUTINE rd_amber_section_i3(parser, section, array1, array2, array3, dim)
    1087             :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1088             :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: section
    1089             :       INTEGER, DIMENSION(:)                              :: array1, array2, array3
    1090             :       INTEGER, INTENT(IN)                                :: dim
    1091             : 
    1092             :       INTEGER                                            :: i
    1093             :       LOGICAL                                            :: my_end
    1094             : 
    1095          72 :       CALL parser_get_next_line(parser, 1, at_end=my_end)
    1096          72 :       i = 1
    1097      114050 :       DO WHILE ((i <= dim) .AND. (.NOT. my_end))
    1098             :          !array1
    1099      113978 :          IF (parser_test_next_token(parser) == "EOL") &
    1100      125336 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1101      113978 :          IF (my_end) EXIT
    1102      113978 :          CALL parser_get_object(parser, array1(i))
    1103             :          !array2
    1104      113978 :          IF (parser_test_next_token(parser) == "EOL") &
    1105      125398 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1106      113978 :          IF (my_end) EXIT
    1107      113978 :          CALL parser_get_object(parser, array2(i))
    1108             :          !array3
    1109      113978 :          IF (parser_test_next_token(parser) == "EOL") &
    1110      125356 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1111      113978 :          IF (my_end) EXIT
    1112      113978 :          CALL parser_get_object(parser, array3(i))
    1113      113978 :          i = i + 1
    1114             :       END DO
    1115             :       ! Trigger end of file aborting
    1116          72 :       IF (my_end .AND. (i <= dim)) &
    1117             :          CALL cp_abort(__LOCATION__, &
    1118           0 :                        "End of file while reading section "//TRIM(section)//" in amber topology file!")
    1119          72 :    END SUBROUTINE rd_amber_section_i3
    1120             : 
    1121             : ! **************************************************************************************************
    1122             : !> \brief Set of Low level subroutines reading section for parmtop
    1123             : !>        reading 4 arrays of integers of length dim
    1124             : !> \param parser ...
    1125             : !> \param section ...
    1126             : !> \param array1 ...
    1127             : !> \param array2 ...
    1128             : !> \param array3 ...
    1129             : !> \param array4 ...
    1130             : !> \param dim ...
    1131             : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1132             : ! **************************************************************************************************
    1133          72 :    SUBROUTINE rd_amber_section_i4(parser, section, array1, array2, array3, array4, dim)
    1134             :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1135             :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: section
    1136             :       INTEGER, DIMENSION(:)                              :: array1, array2, array3, array4
    1137             :       INTEGER, INTENT(IN)                                :: dim
    1138             : 
    1139             :       INTEGER                                            :: i
    1140             :       LOGICAL                                            :: my_end
    1141             : 
    1142          72 :       CALL parser_get_next_line(parser, 1, at_end=my_end)
    1143          72 :       i = 1
    1144       91440 :       DO WHILE ((i <= dim) .AND. (.NOT. my_end))
    1145             :          !array1
    1146       91368 :          IF (parser_test_next_token(parser) == "EOL") &
    1147      109606 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1148       91368 :          IF (my_end) EXIT
    1149       91368 :          CALL parser_get_object(parser, array1(i))
    1150             :          !array2
    1151       91368 :          IF (parser_test_next_token(parser) == "EOL") &
    1152       91368 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1153       91368 :          IF (my_end) EXIT
    1154       91368 :          CALL parser_get_object(parser, array2(i))
    1155             :          !array3
    1156       91368 :          IF (parser_test_next_token(parser) == "EOL") &
    1157      109634 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1158       91368 :          IF (my_end) EXIT
    1159       91368 :          CALL parser_get_object(parser, array3(i))
    1160             :          !array4
    1161       91368 :          IF (parser_test_next_token(parser) == "EOL") &
    1162       91368 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1163       91368 :          IF (my_end) EXIT
    1164       91368 :          CALL parser_get_object(parser, array4(i))
    1165       91368 :          i = i + 1
    1166             :       END DO
    1167             :       ! Trigger end of file aborting
    1168          72 :       IF (my_end .AND. (i <= dim)) &
    1169             :          CALL cp_abort(__LOCATION__, &
    1170           0 :                        "End of file while reading section "//TRIM(section)//" in amber topology file!")
    1171          72 :    END SUBROUTINE rd_amber_section_i4
    1172             : 
    1173             : ! **************************************************************************************************
    1174             : !> \brief Set of Low level subroutines reading section for parmtop
    1175             : !>        reading 5 arrays of integers of length dim
    1176             : !> \param parser ...
    1177             : !> \param section ...
    1178             : !> \param array1 ...
    1179             : !> \param array2 ...
    1180             : !> \param array3 ...
    1181             : !> \param array4 ...
    1182             : !> \param array5 ...
    1183             : !> \param dim ...
    1184             : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1185             : ! **************************************************************************************************
    1186          72 :    SUBROUTINE rd_amber_section_i5(parser, section, array1, array2, array3, array4, &
    1187          72 :                                   array5, dim)
    1188             :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1189             :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: section
    1190             :       INTEGER, DIMENSION(:)                              :: array1, array2, array3, array4, array5
    1191             :       INTEGER, INTENT(IN)                                :: dim
    1192             : 
    1193             :       INTEGER                                            :: i
    1194             :       LOGICAL                                            :: my_end
    1195             : 
    1196          72 :       CALL parser_get_next_line(parser, 1, at_end=my_end)
    1197          72 :       i = 1
    1198      101852 :       DO WHILE ((i <= dim) .AND. (.NOT. my_end))
    1199             :          !array1
    1200      101780 :          IF (parser_test_next_token(parser) == "EOL") &
    1201      152634 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1202      101780 :          IF (my_end) EXIT
    1203      101780 :          CALL parser_get_object(parser, array1(i))
    1204             :          !array2
    1205      101780 :          IF (parser_test_next_token(parser) == "EOL") &
    1206      101780 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1207      101780 :          IF (my_end) EXIT
    1208      101780 :          CALL parser_get_object(parser, array2(i))
    1209             :          !array3
    1210      101780 :          IF (parser_test_next_token(parser) == "EOL") &
    1211      101780 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1212      101780 :          IF (my_end) EXIT
    1213      101780 :          CALL parser_get_object(parser, array3(i))
    1214             :          !array4
    1215      101780 :          IF (parser_test_next_token(parser) == "EOL") &
    1216      101780 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1217      101780 :          IF (my_end) EXIT
    1218      101780 :          CALL parser_get_object(parser, array4(i))
    1219             :          !array5
    1220      101780 :          IF (parser_test_next_token(parser) == "EOL") &
    1221      101780 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1222      101780 :          IF (my_end) EXIT
    1223      101780 :          CALL parser_get_object(parser, array5(i))
    1224      101780 :          i = i + 1
    1225             :       END DO
    1226             :       ! Trigger end of file aborting
    1227          72 :       IF (my_end .AND. (i <= dim)) &
    1228             :          CALL cp_abort(__LOCATION__, &
    1229           0 :                        "End of file while reading section "//TRIM(section)//" in amber topology file!")
    1230          72 :    END SUBROUTINE rd_amber_section_i5
    1231             : 
    1232             : ! **************************************************************************************************
    1233             : !> \brief Set of Low level subroutines reading section for parmtop
    1234             : !>        reading 1 array of strings of length dim
    1235             : !> \param parser ...
    1236             : !> \param section ...
    1237             : !> \param array1 ...
    1238             : !> \param dim ...
    1239             : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1240             : ! **************************************************************************************************
    1241          44 :    SUBROUTINE rd_amber_section_c1(parser, section, array1, dim)
    1242             :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1243             :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: section
    1244             :       CHARACTER(LEN=default_string_length), DIMENSION(:) :: array1
    1245             :       INTEGER, INTENT(IN)                                :: dim
    1246             : 
    1247             :       INTEGER                                            :: i
    1248             :       LOGICAL                                            :: my_end
    1249             : 
    1250          44 :       CALL parser_get_next_line(parser, 1, at_end=my_end)
    1251          44 :       i = 1
    1252      101612 :       DO WHILE ((i <= dim) .AND. (.NOT. my_end))
    1253      101568 :          IF (parser_test_next_token(parser) == "EOL") &
    1254      106634 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1255      101568 :          IF (my_end) EXIT
    1256      101568 :          CALL parser_get_object(parser, array1(i), lower_to_upper=.TRUE.)
    1257      101568 :          i = i + 1
    1258             :       END DO
    1259             :       ! Trigger end of file aborting
    1260          44 :       IF (my_end .AND. (i <= dim)) &
    1261             :          CALL cp_abort(__LOCATION__, &
    1262           0 :                        "End of file while reading section "//TRIM(section)//" in amber topology file!")
    1263          44 :    END SUBROUTINE rd_amber_section_c1
    1264             : 
    1265             : ! **************************************************************************************************
    1266             : !> \brief Set of Low level subroutines reading section for parmtop
    1267             : !>        reading 1 array of strings of length dim
    1268             : !> \param parser ...
    1269             : !> \param section ...
    1270             : !> \param array1 ...
    1271             : !> \param dim ...
    1272             : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1273             : ! **************************************************************************************************
    1274         198 :    SUBROUTINE rd_amber_section_r1(parser, section, array1, dim)
    1275             :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1276             :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: section
    1277             :       REAL(KIND=dp), DIMENSION(:)                        :: array1
    1278             :       INTEGER, INTENT(IN)                                :: dim
    1279             : 
    1280             :       INTEGER                                            :: i
    1281             :       LOGICAL                                            :: my_end
    1282             : 
    1283         198 :       CALL parser_get_next_line(parser, 1, at_end=my_end)
    1284         198 :       i = 1
    1285      162032 :       DO WHILE ((i <= dim) .AND. (.NOT. my_end))
    1286      161834 :          IF (parser_test_next_token(parser) == "EOL") &
    1287      194108 :             CALL parser_get_next_line(parser, 1, at_end=my_end)
    1288      161834 :          IF (my_end) EXIT
    1289      161834 :          CALL parser_get_object(parser, array1(i))
    1290      161834 :          i = i + 1
    1291             :       END DO
    1292             :       ! Trigger end of file aborting
    1293         198 :       IF (my_end .AND. (i <= dim)) &
    1294             :          CALL cp_abort(__LOCATION__, &
    1295           0 :                        "End of file while reading section "//TRIM(section)//" in amber topology file!")
    1296         198 :    END SUBROUTINE rd_amber_section_r1
    1297             : 
    1298             : ! **************************************************************************************************
    1299             : !> \brief Check the version of the AMBER topology file (we can handle from v8 on)
    1300             : !> \param parser ...
    1301             : !> \param section ...
    1302             : !> \param input_format ...
    1303             : !> \return ...
    1304             : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1305             : ! **************************************************************************************************
    1306        1412 :    FUNCTION get_section_parmtop(parser, section, input_format) RESULT(another_section)
    1307             :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1308             :       CHARACTER(LEN=default_string_length), INTENT(OUT)  :: section, input_format
    1309             :       LOGICAL                                            :: another_section
    1310             : 
    1311             :       INTEGER                                            :: end_f, indflag, start_f
    1312             :       LOGICAL                                            :: found, my_end
    1313             : 
    1314        1412 :       CALL parser_search_string(parser, "%FLAG", .TRUE., found, begin_line=.TRUE.)
    1315        1412 :       IF (found) THEN
    1316             :          ! section label
    1317        1376 :          indflag = INDEX(parser%input_line, "%FLAG") + LEN_TRIM("%FLAG")
    1318        2752 :          DO WHILE (INDEX(parser%input_line(indflag:indflag), " ") /= 0)
    1319        1376 :             indflag = indflag + 1
    1320             :          END DO
    1321        1376 :          section = TRIM(parser%input_line(indflag:))
    1322             :          ! Input format
    1323        1376 :          CALL parser_get_next_line(parser, 1, at_end=my_end)
    1324        1376 :          IF (INDEX(parser%input_line, "%FORMAT") == 0 .OR. my_end) &
    1325           0 :             CPABORT("Expecting %FORMAT. Not found! Abort reading of AMBER topology file!")
    1326             : 
    1327        1376 :          start_f = INDEX(parser%input_line, "(")
    1328        1376 :          end_f = INDEX(parser%input_line, ")")
    1329        1376 :          input_format = parser%input_line(start_f:end_f)
    1330             :          another_section = .TRUE.
    1331             :       ELSE
    1332             :          another_section = .FALSE.
    1333             :       END IF
    1334        1412 :    END FUNCTION get_section_parmtop
    1335             : 
    1336             : ! **************************************************************************************************
    1337             : !> \brief Check the version of the AMBER topology file (we can handle from v8 on)
    1338             : !> \param parser ...
    1339             : !> \param output_unit ...
    1340             : !> \return ...
    1341             : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
    1342             : ! **************************************************************************************************
    1343          36 :    FUNCTION check_amber_8_std(parser, output_unit) RESULT(found_AMBER_V8)
    1344             :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
    1345             :       INTEGER, INTENT(IN)                                :: output_unit
    1346             :       LOGICAL                                            :: found_AMBER_V8
    1347             : 
    1348          36 :       CALL parser_search_string(parser, "%VERSION ", .TRUE., found_AMBER_V8, begin_line=.TRUE.)
    1349          36 :       IF (.NOT. found_AMBER_V8) &
    1350             :          CALL cp_abort(__LOCATION__, &
    1351             :                        "This is not an AMBER V.8 PRMTOP format file. Cannot interpret older "// &
    1352           0 :                        "AMBER file formats. ")
    1353          39 :       IF (output_unit > 0) WRITE (output_unit, '(" AMBER_INFO| ",A)') "Amber PrmTop V.8 or greater.", &
    1354           6 :          TRIM(parser%input_line)
    1355             : 
    1356          36 :    END FUNCTION check_amber_8_std
    1357             : 
    1358             : ! **************************************************************************************************
    1359             : !> \brief Post processing of forcefield information related to bonds
    1360             : !> \param label_a ...
    1361             : !> \param label_b ...
    1362             : !> \param k ...
    1363             : !> \param r0 ...
    1364             : !> \param particle_set ...
    1365             : !> \param ibond ...
    1366             : !> \param nbond ...
    1367             : !> \param ib ...
    1368             : !> \param jb ...
    1369             : !> \param icb ...
    1370             : !> \param rk ...
    1371             : !> \param req ...
    1372             : !> \author Teodoro Laino [tlaino] - 11.2008
    1373             : ! **************************************************************************************************
    1374          28 :    SUBROUTINE post_process_bonds_info(label_a, label_b, k, r0, particle_set, ibond, &
    1375          28 :                                       nbond, ib, jb, icb, rk, req)
    1376             :       CHARACTER(LEN=default_string_length), &
    1377             :          DIMENSION(:), POINTER                           :: label_a, label_b
    1378             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: k, r0
    1379             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1380             :       INTEGER, INTENT(INOUT)                             :: ibond
    1381             :       INTEGER, INTENT(IN)                                :: nbond
    1382             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: ib, jb, icb
    1383             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rk, req
    1384             : 
    1385             :       CHARACTER(len=*), PARAMETER :: routineN = 'post_process_bonds_info'
    1386             : 
    1387             :       CHARACTER(LEN=default_string_length)               :: name_atm_a, name_atm_b
    1388             :       CHARACTER(LEN=default_string_length), &
    1389          28 :          ALLOCATABLE, DIMENSION(:, :)                    :: work_label
    1390             :       INTEGER                                            :: handle, i
    1391          28 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: iwork
    1392             :       LOGICAL                                            :: l_dum
    1393             : 
    1394          28 :       CALL timeset(routineN, handle)
    1395          28 :       IF (nbond /= 0) THEN
    1396          78 :          ALLOCATE (work_label(2, nbond))
    1397          78 :          ALLOCATE (iwork(nbond))
    1398       56826 :          DO i = 1, nbond
    1399       56800 :             name_atm_a = particle_set(ib(i))%atomic_kind%name
    1400       56800 :             name_atm_b = particle_set(jb(i))%atomic_kind%name
    1401       56800 :             l_dum = qmmm_ff_precond_only_qm(id1=name_atm_a, id2=name_atm_b)
    1402       56800 :             work_label(1, i) = name_atm_a
    1403       56826 :             work_label(2, i) = name_atm_b
    1404             :          END DO
    1405          26 :          CALL sort(work_label, 1, nbond, 1, 2, iwork)
    1406             : 
    1407          26 :          ibond = ibond + 1
    1408             :          ! In case we need more space ... give it up...
    1409          26 :          IF (ibond > SIZE(label_a)) THEN
    1410           2 :             CALL reallocate(label_a, 1, INT(buffer_size + ibond*1.5_dp))
    1411           2 :             CALL reallocate(label_b, 1, INT(buffer_size + ibond*1.5_dp))
    1412           2 :             CALL reallocate(k, 1, INT(buffer_size + ibond*1.5_dp))
    1413           2 :             CALL reallocate(r0, 1, INT(buffer_size + ibond*1.5_dp))
    1414             :          END IF
    1415          26 :          label_a(ibond) = work_label(1, 1)
    1416          26 :          label_b(ibond) = work_label(2, 1)
    1417          26 :          k(ibond) = rk(icb(iwork(1)))
    1418          26 :          r0(ibond) = req(icb(iwork(1)))
    1419             : 
    1420       56800 :          DO i = 2, nbond
    1421       56774 :             IF ((work_label(1, i) /= label_a(ibond)) .OR. &
    1422          26 :                 (work_label(2, i) /= label_b(ibond))) THEN
    1423        1698 :                ibond = ibond + 1
    1424             :                ! In case we need more space ... give it up...
    1425        1698 :                IF (ibond > SIZE(label_a)) THEN
    1426          84 :                   CALL reallocate(label_a, 1, INT(buffer_size + ibond*1.5_dp))
    1427          84 :                   CALL reallocate(label_b, 1, INT(buffer_size + ibond*1.5_dp))
    1428          84 :                   CALL reallocate(k, 1, INT(buffer_size + ibond*1.5_dp))
    1429          84 :                   CALL reallocate(r0, 1, INT(buffer_size + ibond*1.5_dp))
    1430             :                END IF
    1431        1698 :                label_a(ibond) = work_label(1, i)
    1432        1698 :                label_b(ibond) = work_label(2, i)
    1433        1698 :                k(ibond) = rk(icb(iwork(i)))
    1434        1698 :                r0(ibond) = req(icb(iwork(i)))
    1435             :             END IF
    1436             :          END DO
    1437             : 
    1438          26 :          DEALLOCATE (work_label)
    1439          26 :          DEALLOCATE (iwork)
    1440             :       END IF
    1441          28 :       CALL timestop(handle)
    1442          28 :    END SUBROUTINE post_process_bonds_info
    1443             : 
    1444             : ! **************************************************************************************************
    1445             : !> \brief Post processing of forcefield information related to bends
    1446             : !> \param label_a ...
    1447             : !> \param label_b ...
    1448             : !> \param label_c ...
    1449             : !> \param k ...
    1450             : !> \param theta0 ...
    1451             : !> \param particle_set ...
    1452             : !> \param itheta ...
    1453             : !> \param ntheta ...
    1454             : !> \param it ...
    1455             : !> \param jt ...
    1456             : !> \param kt ...
    1457             : !> \param ict ...
    1458             : !> \param tk ...
    1459             : !> \param teq ...
    1460             : !> \author Teodoro Laino [tlaino] - 11.2008
    1461             : ! **************************************************************************************************
    1462          28 :    SUBROUTINE post_process_bends_info(label_a, label_b, label_c, k, theta0, &
    1463          28 :                                       particle_set, itheta, ntheta, it, jt, kt, ict, tk, teq)
    1464             :       CHARACTER(LEN=default_string_length), &
    1465             :          DIMENSION(:), POINTER                           :: label_a, label_b, label_c
    1466             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: k, theta0
    1467             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1468             :       INTEGER, INTENT(INOUT)                             :: itheta
    1469             :       INTEGER, INTENT(IN)                                :: ntheta
    1470             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: it, jt, kt, ict
    1471             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: tk, teq
    1472             : 
    1473             :       CHARACTER(len=*), PARAMETER :: routineN = 'post_process_bends_info'
    1474             : 
    1475             :       CHARACTER(LEN=default_string_length)               :: name_atm_a, name_atm_b, name_atm_c
    1476             :       CHARACTER(LEN=default_string_length), &
    1477          28 :          ALLOCATABLE, DIMENSION(:, :)                    :: work_label
    1478             :       INTEGER                                            :: handle, i
    1479          28 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: iwork
    1480             :       LOGICAL                                            :: l_dum
    1481             : 
    1482          28 :       CALL timeset(routineN, handle)
    1483          28 :       IF (ntheta /= 0) THEN
    1484          78 :          ALLOCATE (work_label(3, ntheta))
    1485          78 :          ALLOCATE (iwork(ntheta))
    1486       45398 :          DO i = 1, ntheta
    1487       45372 :             name_atm_a = particle_set(it(i))%atomic_kind%name
    1488       45372 :             name_atm_b = particle_set(jt(i))%atomic_kind%name
    1489       45372 :             name_atm_c = particle_set(kt(i))%atomic_kind%name
    1490             :             l_dum = qmmm_ff_precond_only_qm(id1=name_atm_a, id2=name_atm_b, &
    1491       45372 :                                             id3=name_atm_c)
    1492       45372 :             work_label(1, i) = name_atm_a
    1493       45372 :             work_label(2, i) = name_atm_b
    1494       45398 :             work_label(3, i) = name_atm_c
    1495             :          END DO
    1496             : 
    1497          26 :          CALL sort(work_label, 1, ntheta, 1, 3, iwork)
    1498             : 
    1499          26 :          itheta = itheta + 1
    1500             :          ! In case we need more space ... give it up...
    1501          26 :          IF (itheta > SIZE(label_a)) THEN
    1502           2 :             CALL reallocate(label_a, 1, INT(buffer_size + itheta*1.5_dp))
    1503           2 :             CALL reallocate(label_b, 1, INT(buffer_size + itheta*1.5_dp))
    1504           2 :             CALL reallocate(label_c, 1, INT(buffer_size + itheta*1.5_dp))
    1505           2 :             CALL reallocate(k, 1, INT(buffer_size + itheta*1.5_dp))
    1506           2 :             CALL reallocate(theta0, 1, INT(buffer_size + itheta*1.5_dp))
    1507             :          END IF
    1508          26 :          label_a(itheta) = work_label(1, 1)
    1509          26 :          label_b(itheta) = work_label(2, 1)
    1510          26 :          label_c(itheta) = work_label(3, 1)
    1511          26 :          k(itheta) = tk(ict(iwork(1)))
    1512          26 :          theta0(itheta) = teq(ict(iwork(1)))
    1513             : 
    1514       45372 :          DO i = 2, ntheta
    1515             :             IF ((work_label(1, i) /= label_a(itheta)) .OR. &
    1516       45346 :                 (work_label(2, i) /= label_b(itheta)) .OR. &
    1517          26 :                 (work_label(3, i) /= label_c(itheta))) THEN
    1518        3610 :                itheta = itheta + 1
    1519             :                ! In case we need more space ... give it up...
    1520        3610 :                IF (itheta > SIZE(label_a)) THEN
    1521         102 :                   CALL reallocate(label_a, 1, INT(buffer_size + itheta*1.5_dp))
    1522         102 :                   CALL reallocate(label_b, 1, INT(buffer_size + itheta*1.5_dp))
    1523         102 :                   CALL reallocate(label_c, 1, INT(buffer_size + itheta*1.5_dp))
    1524         102 :                   CALL reallocate(k, 1, INT(buffer_size + itheta*1.5_dp))
    1525         102 :                   CALL reallocate(theta0, 1, INT(buffer_size + itheta*1.5_dp))
    1526             :                END IF
    1527        3610 :                label_a(itheta) = work_label(1, i)
    1528        3610 :                label_b(itheta) = work_label(2, i)
    1529        3610 :                label_c(itheta) = work_label(3, i)
    1530        3610 :                k(itheta) = tk(ict(iwork(i)))
    1531        3610 :                theta0(itheta) = teq(ict(iwork(i)))
    1532             :             END IF
    1533             :          END DO
    1534             : 
    1535          26 :          DEALLOCATE (work_label)
    1536          26 :          DEALLOCATE (iwork)
    1537             :       END IF
    1538          28 :       CALL timestop(handle)
    1539          28 :    END SUBROUTINE post_process_bends_info
    1540             : 
    1541             : ! **************************************************************************************************
    1542             : !> \brief Post processing of forcefield information related to torsions
    1543             : !> \param label_a ...
    1544             : !> \param label_b ...
    1545             : !> \param label_c ...
    1546             : !> \param label_d ...
    1547             : !> \param k ...
    1548             : !> \param m ...
    1549             : !> \param phi0 ...
    1550             : !> \param particle_set ...
    1551             : !> \param iphi ...
    1552             : !> \param nphi ...
    1553             : !> \param ip ...
    1554             : !> \param jp ...
    1555             : !> \param kp ...
    1556             : !> \param lp ...
    1557             : !> \param icp ...
    1558             : !> \param pk ...
    1559             : !> \param pn ...
    1560             : !> \param phase ...
    1561             : !> \author Teodoro Laino [tlaino] - 11.2008
    1562             : ! **************************************************************************************************
    1563          28 :    SUBROUTINE post_process_torsions_info(label_a, label_b, label_c, label_d, k, &
    1564          28 :                                          m, phi0, particle_set, iphi, nphi, ip, jp, kp, lp, icp, pk, pn, phase)
    1565             :       CHARACTER(LEN=default_string_length), &
    1566             :          DIMENSION(:), POINTER                           :: label_a, label_b, label_c, label_d
    1567             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: k
    1568             :       INTEGER, DIMENSION(:), POINTER                     :: m
    1569             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: phi0
    1570             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1571             :       INTEGER, INTENT(INOUT)                             :: iphi
    1572             :       INTEGER, INTENT(IN)                                :: nphi
    1573             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: ip, jp, kp, lp, icp
    1574             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: pk, pn, phase
    1575             : 
    1576             :       CHARACTER(len=*), PARAMETER :: routineN = 'post_process_torsions_info'
    1577             : 
    1578             :       CHARACTER(LEN=default_string_length)               :: name_atm_a, name_atm_b, name_atm_c, &
    1579             :                                                             name_atm_d
    1580             :       CHARACTER(LEN=default_string_length), &
    1581          28 :          ALLOCATABLE, DIMENSION(:, :)                    :: work_label
    1582             :       INTEGER                                            :: handle, i
    1583          28 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: iwork
    1584             :       LOGICAL                                            :: l_dum
    1585             : 
    1586          28 :       CALL timeset(routineN, handle)
    1587          28 :       IF (nphi /= 0) THEN
    1588          72 :          ALLOCATE (work_label(6, nphi))
    1589          72 :          ALLOCATE (iwork(nphi))
    1590       50412 :          DO i = 1, nphi
    1591       50388 :             name_atm_a = particle_set(ip(i))%atomic_kind%name
    1592       50388 :             name_atm_b = particle_set(jp(i))%atomic_kind%name
    1593       50388 :             name_atm_c = particle_set(kp(i))%atomic_kind%name
    1594       50388 :             name_atm_d = particle_set(lp(i))%atomic_kind%name
    1595             :             l_dum = qmmm_ff_precond_only_qm(id1=name_atm_a, id2=name_atm_b, &
    1596       50388 :                                             id3=name_atm_c, id4=name_atm_d)
    1597       50388 :             work_label(1, i) = name_atm_a
    1598       50388 :             work_label(2, i) = name_atm_b
    1599       50388 :             work_label(3, i) = name_atm_c
    1600       50388 :             work_label(4, i) = name_atm_d
    1601             :             ! Phase and multiplicity must be kept into account
    1602             :             ! for the ordering of the torsions
    1603       50388 :             work_label(5, i) = TRIM(ADJUSTL(cp_to_string(phase(icp(i)))))
    1604       50412 :             work_label(6, i) = TRIM(ADJUSTL(cp_to_string(pn(icp(i)))))
    1605             :          END DO
    1606             : 
    1607          24 :          CALL sort(work_label, 1, nphi, 1, 6, iwork)
    1608             : 
    1609          24 :          iphi = iphi + 1
    1610             :          ! In case we need more space ... give it up...
    1611          24 :          IF (iphi > SIZE(label_a)) THEN
    1612           0 :             CALL reallocate(label_a, 1, INT(buffer_size + iphi*1.5_dp))
    1613           0 :             CALL reallocate(label_b, 1, INT(buffer_size + iphi*1.5_dp))
    1614           0 :             CALL reallocate(label_c, 1, INT(buffer_size + iphi*1.5_dp))
    1615           0 :             CALL reallocate(label_d, 1, INT(buffer_size + iphi*1.5_dp))
    1616           0 :             CALL reallocate(k, 1, INT(buffer_size + iphi*1.5_dp))
    1617           0 :             CALL reallocate(m, 1, INT(buffer_size + iphi*1.5_dp))
    1618           0 :             CALL reallocate(phi0, 1, INT(buffer_size + iphi*1.5_dp))
    1619             :          END IF
    1620          24 :          label_a(iphi) = work_label(1, 1)
    1621          24 :          label_b(iphi) = work_label(2, 1)
    1622          24 :          label_c(iphi) = work_label(3, 1)
    1623          24 :          label_d(iphi) = work_label(4, 1)
    1624          24 :          k(iphi) = pk(icp(iwork(1)))
    1625          24 :          m(iphi) = NINT(pn(icp(iwork(1))))
    1626          24 :          IF (m(iphi) - pn(icp(iwork(1))) .GT. EPSILON(1.0_dp)) THEN
    1627             :             ! non integer torsions not supported
    1628           0 :             CPABORT("")
    1629             :          END IF
    1630             : 
    1631          24 :          phi0(iphi) = phase(icp(iwork(1)))
    1632             : 
    1633       50388 :          DO i = 2, nphi
    1634             :             ! We don't consider the possibility that a torsion can have same
    1635             :             ! phase, periodicity but different value of k.. in this case the
    1636             :             ! potential should be summed-up
    1637             :             IF ((work_label(1, i) /= label_a(iphi)) .OR. &
    1638             :                 (work_label(2, i) /= label_b(iphi)) .OR. &
    1639             :                 (work_label(3, i) /= label_c(iphi)) .OR. &
    1640             :                 (work_label(4, i) /= label_d(iphi)) .OR. &
    1641       50364 :                 (pn(icp(iwork(i))) /= m(iphi)) .OR. &
    1642          24 :                 (phase(icp(iwork(i))) /= phi0(iphi))) THEN
    1643       10058 :                iphi = iphi + 1
    1644             :                ! In case we need more space ... give it up...
    1645       10058 :                IF (iphi > SIZE(label_a)) THEN
    1646         130 :                   CALL reallocate(label_a, 1, INT(buffer_size + iphi*1.5_dp))
    1647         130 :                   CALL reallocate(label_b, 1, INT(buffer_size + iphi*1.5_dp))
    1648         130 :                   CALL reallocate(label_c, 1, INT(buffer_size + iphi*1.5_dp))
    1649         130 :                   CALL reallocate(label_d, 1, INT(buffer_size + iphi*1.5_dp))
    1650         130 :                   CALL reallocate(k, 1, INT(buffer_size + iphi*1.5_dp))
    1651         130 :                   CALL reallocate(m, 1, INT(buffer_size + iphi*1.5_dp))
    1652         130 :                   CALL reallocate(phi0, 1, INT(buffer_size + iphi*1.5_dp))
    1653             :                END IF
    1654       10058 :                label_a(iphi) = work_label(1, i)
    1655       10058 :                label_b(iphi) = work_label(2, i)
    1656       10058 :                label_c(iphi) = work_label(3, i)
    1657       10058 :                label_d(iphi) = work_label(4, i)
    1658       10058 :                k(iphi) = pk(icp(iwork(i)))
    1659       10058 :                m(iphi) = NINT(pn(icp(iwork(i))))
    1660       10058 :                IF (m(iphi) - pn(icp(iwork(i))) .GT. EPSILON(1.0_dp)) THEN
    1661             :                   ! non integer torsions not supported
    1662           0 :                   CPABORT("")
    1663             :                END IF
    1664       10058 :                phi0(iphi) = phase(icp(iwork(i)))
    1665             :             END IF
    1666             :          END DO
    1667             : 
    1668          24 :          DEALLOCATE (work_label)
    1669          24 :          DEALLOCATE (iwork)
    1670             :       END IF
    1671          28 :       CALL timestop(handle)
    1672          28 :    END SUBROUTINE post_process_torsions_info
    1673             : 
    1674             : ! **************************************************************************************************
    1675             : !> \brief Post processing of forcefield information related to Lennard-Jones
    1676             : !> \param atom_label ...
    1677             : !> \param eps ...
    1678             : !> \param sigma ...
    1679             : !> \param particle_set ...
    1680             : !> \param ntypes ...
    1681             : !> \param nsize ...
    1682             : !> \param iac ...
    1683             : !> \param ico ...
    1684             : !> \param cn1 ...
    1685             : !> \param cn2 ...
    1686             : !> \param natom ...
    1687             : !> \author Teodoro Laino [tlaino] - 11.2008
    1688             : ! **************************************************************************************************
    1689          14 :    SUBROUTINE post_process_LJ_info(atom_label, eps, sigma, particle_set, &
    1690          14 :                                    ntypes, nsize, iac, ico, cn1, cn2, natom)
    1691             :       CHARACTER(LEN=default_string_length), &
    1692             :          DIMENSION(:), POINTER                           :: atom_label
    1693             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eps, sigma
    1694             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1695             :       INTEGER, INTENT(IN)                                :: ntypes
    1696             :       INTEGER, INTENT(INOUT)                             :: nsize
    1697             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: iac, ico
    1698             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: cn1, cn2
    1699             :       INTEGER, INTENT(IN)                                :: natom
    1700             : 
    1701             :       CHARACTER(len=*), PARAMETER :: routineN = 'post_process_LJ_info'
    1702             : 
    1703             :       CHARACTER(LEN=default_string_length)               :: name_atm_a
    1704             :       CHARACTER(LEN=default_string_length), &
    1705          14 :          ALLOCATABLE, DIMENSION(:)                       :: work_label
    1706             :       INTEGER                                            :: handle, i
    1707          14 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: iwork
    1708             :       LOGICAL                                            :: check, l_dum
    1709             :       REAL(KIND=dp)                                      :: F12, F6, my_eps, my_sigma, sigma6
    1710             : 
    1711          14 :       CALL timeset(routineN, handle)
    1712          42 :       ALLOCATE (work_label(natom))
    1713          42 :       ALLOCATE (iwork(natom))
    1714       78508 :       DO i = 1, natom
    1715       78494 :          name_atm_a = particle_set(i)%atomic_kind%name
    1716       78494 :          l_dum = qmmm_ff_precond_only_qm(id1=name_atm_a)
    1717       78508 :          work_label(i) = name_atm_a
    1718             :       END DO
    1719          14 :       CALL sort(work_label, natom, iwork)
    1720             : 
    1721          14 :       nsize = nsize + 1
    1722          14 :       IF (nsize > SIZE(atom_label)) THEN
    1723           0 :          CALL reallocate(atom_label, 1, INT(buffer_size + nsize*1.5_dp))
    1724           0 :          CALL reallocate(eps, 1, INT(buffer_size + nsize*1.5_dp))
    1725           0 :          CALL reallocate(sigma, 1, INT(buffer_size + nsize*1.5_dp))
    1726             :       END IF
    1727          14 :       F12 = cn1(ico(ntypes*(iac(iwork(1)) - 1) + iac(iwork(1))))
    1728          14 :       F6 = cn2(ico(ntypes*(iac(iwork(1)) - 1) + iac(iwork(1))))
    1729          14 :       check = (F6 == 0.0_dp) .EQV. (F12 == 0.0_dp)
    1730          14 :       CPASSERT(check)
    1731          14 :       my_sigma = 0.0_dp
    1732          14 :       my_eps = 0.0_dp
    1733          14 :       IF (F6 /= 0.0_dp) THEN
    1734          14 :          sigma6 = (2.0_dp*F12/F6)
    1735          14 :          my_sigma = sigma6**(1.0_dp/6.0_dp)
    1736          14 :          my_eps = F6/(2.0_dp*sigma6)
    1737             :       END IF
    1738          14 :       atom_label(nsize) = work_label(1)
    1739          14 :       sigma(nsize) = my_sigma/2.0_dp
    1740          14 :       eps(nsize) = my_eps
    1741             : 
    1742       78494 :       DO i = 2, natom
    1743       78494 :          IF (work_label(i) /= atom_label(nsize)) THEN
    1744        1446 :             nsize = nsize + 1
    1745             :             ! In case we need more space ... give it up...
    1746        1446 :             IF (nsize > SIZE(atom_label)) THEN
    1747          84 :                CALL reallocate(atom_label, 1, INT(buffer_size + nsize*1.5_dp))
    1748          84 :                CALL reallocate(eps, 1, INT(buffer_size + nsize*1.5_dp))
    1749          84 :                CALL reallocate(sigma, 1, INT(buffer_size + nsize*1.5_dp))
    1750             :             END IF
    1751        1446 :             F12 = cn1(ico(ntypes*(iac(iwork(i)) - 1) + iac(iwork(i))))
    1752        1446 :             F6 = cn2(ico(ntypes*(iac(iwork(i)) - 1) + iac(iwork(i))))
    1753        1446 :             check = (F6 == 0.0_dp) .EQV. (F12 == 0.0_dp)
    1754        1446 :             CPASSERT(check)
    1755        1446 :             my_sigma = 0.0_dp
    1756        1446 :             my_eps = 0.0_dp
    1757        1446 :             IF (F6 /= 0.0_dp) THEN
    1758        1422 :                sigma6 = (2.0_dp*F12/F6)
    1759        1422 :                my_sigma = sigma6**(1.0_dp/6.0_dp)
    1760        1422 :                my_eps = F6/(2.0_dp*sigma6)
    1761             :             END IF
    1762        1446 :             atom_label(nsize) = work_label(i)
    1763        1446 :             sigma(nsize) = my_sigma/2.0_dp
    1764        1446 :             eps(nsize) = my_eps
    1765             :          END IF
    1766             :       END DO
    1767             : 
    1768          14 :       DEALLOCATE (work_label)
    1769          14 :       DEALLOCATE (iwork)
    1770          14 :       CALL timestop(handle)
    1771          14 :    END SUBROUTINE post_process_LJ_info
    1772             : 
    1773             : END MODULE topology_amber
    1774             : 

Generated by: LCOV version 1.15