LCOV - code coverage report
Current view: top level - src - topology_generate_util.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:c24029e) Lines: 95.2 % 1066 1015
Test Date: 2026-07-04 06:36:57 Functions: 100.0 % 15 15

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Collection of subroutine needed for topology related things
      10              : !> \par History
      11              : !>     Teodor Laino 09.2006 - Major rewriting with linear scaling routines
      12              : ! **************************************************************************************************
      13              : MODULE topology_generate_util
      14              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      15              :                                               deallocate_atomic_kind_set,&
      16              :                                               set_atomic_kind
      17              :    USE cell_types,                      ONLY: pbc
      18              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      19              :                                               cp_logger_get_default_io_unit,&
      20              :                                               cp_logger_type,&
      21              :                                               cp_to_string
      22              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      23              :                                               cp_print_key_unit_nr
      24              :    USE cp_units,                        ONLY: cp_unit_to_cp2k
      25              :    USE fist_neighbor_list_types,        ONLY: fist_neighbor_deallocate,&
      26              :                                               fist_neighbor_type
      27              :    USE fist_neighbor_lists,             ONLY: build_fist_neighbor_lists
      28              :    USE input_constants,                 ONLY: do_add,&
      29              :                                               do_bondparm_covalent,&
      30              :                                               do_bondparm_vdw,&
      31              :                                               do_conn_off,&
      32              :                                               do_conn_user,&
      33              :                                               do_remove
      34              :    USE input_section_types,             ONLY: section_vals_get,&
      35              :                                               section_vals_get_subs_vals,&
      36              :                                               section_vals_type,&
      37              :                                               section_vals_val_get
      38              :    USE kinds,                           ONLY: default_string_length,&
      39              :                                               dp
      40              :    USE memory_utilities,                ONLY: reallocate
      41              :    USE message_passing,                 ONLY: mp_para_env_type
      42              :    USE particle_types,                  ONLY: allocate_particle_set,&
      43              :                                               deallocate_particle_set,&
      44              :                                               particle_type
      45              :    USE periodic_table,                  ONLY: get_ptable_info
      46              :    USE qmmm_types_low,                  ONLY: qmmm_env_mm_type
      47              :    USE string_table,                    ONLY: id2str,&
      48              :                                               s2s,&
      49              :                                               str2id
      50              :    USE string_utilities,                ONLY: integer_to_string,&
      51              :                                               uppercase
      52              :    USE topology_types,                  ONLY: atom_info_type,&
      53              :                                               connectivity_info_type,&
      54              :                                               topology_parameters_type
      55              :    USE topology_util,                   ONLY: array1_list_type,&
      56              :                                               array2_list_type,&
      57              :                                               find_molecule,&
      58              :                                               give_back_molecule,&
      59              :                                               reorder_list_array,&
      60              :                                               reorder_structure
      61              :    USE util,                            ONLY: find_boundary,&
      62              :                                               sort
      63              : #include "./base/base_uses.f90"
      64              : 
      65              :    IMPLICIT NONE
      66              : 
      67              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'topology_generate_util'
      68              : 
      69              :    PRIVATE
      70              :    LOGICAL, PARAMETER                   :: debug_this_module = .FALSE.
      71              : 
      72              :    PUBLIC :: topology_generate_bend, &
      73              :              topology_generate_bond, &
      74              :              topology_generate_dihe, &
      75              :              topology_generate_impr, &
      76              :              topology_generate_onfo, &
      77              :              topology_generate_ub, &
      78              :              topology_generate_molecule, &
      79              :              topology_generate_molname
      80              : 
      81              : CONTAINS
      82              : 
      83              : ! **************************************************************************************************
      84              : !> \brief Generates molnames: useful when the connectivity on file does not
      85              : !>        provide them
      86              : !> \param conn_info ...
      87              : !> \param natom ...
      88              : !> \param natom_prev ...
      89              : !> \param nbond_prev ...
      90              : !> \param id_molname ...
      91              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
      92              : ! **************************************************************************************************
      93           22 :    SUBROUTINE topology_generate_molname(conn_info, natom, natom_prev, nbond_prev, &
      94           22 :                                         id_molname)
      95              :       TYPE(connectivity_info_type), POINTER              :: conn_info
      96              :       INTEGER, INTENT(IN)                                :: natom, natom_prev, nbond_prev
      97              :       INTEGER, DIMENSION(:), INTENT(INOUT)               :: id_molname
      98              : 
      99              :       CHARACTER(LEN=default_string_length), PARAMETER    :: basename = "MOL"
     100              : 
     101              :       CHARACTER(LEN=default_string_length)               :: molname
     102              :       INTEGER                                            :: i, id_undef, n, nmol
     103              :       LOGICAL                                            :: check
     104           22 :       TYPE(array1_list_type), ALLOCATABLE, DIMENSION(:)  :: atom_bond_list
     105              : 
     106              :       ! convert a simple list of bonds to a list of bonds per atom
     107              :       ! (each bond is present in the forward and backward direction)
     108              : 
     109        78904 :       ALLOCATE (atom_bond_list(natom))
     110        78860 :       DO i = 1, natom
     111        78860 :          ALLOCATE (atom_bond_list(i)%array1(0))
     112              :       END DO
     113           22 :       n = 0
     114           22 :       IF (ASSOCIATED(conn_info%bond_a)) n = SIZE(conn_info%bond_a) - nbond_prev
     115              :       CALL reorder_structure(atom_bond_list, conn_info%bond_a(nbond_prev + 1:) - natom_prev, &
     116       114378 :                              conn_info%bond_b(nbond_prev + 1:) - natom_prev, n)
     117              : 
     118           22 :       nmol = 0
     119           22 :       id_undef = str2id(s2s("__UNDEF__"))
     120        78882 :       check = ALL(id_molname == id_undef) .OR. ALL(id_molname /= id_undef)
     121           22 :       CPASSERT(check)
     122        78860 :       DO i = 1, natom
     123        78860 :          IF (id_molname(i) == id_undef) THEN
     124        21954 :             molname = TRIM(basename)//ADJUSTL(cp_to_string(nmol))
     125        21954 :             CALL generate_molname_low(i, atom_bond_list, molname, id_molname)
     126        21954 :             nmol = nmol + 1
     127              :          END IF
     128              :       END DO
     129        78860 :       DO i = 1, natom
     130        78860 :          DEALLOCATE (atom_bond_list(i)%array1)
     131              :       END DO
     132           22 :       DEALLOCATE (atom_bond_list)
     133              : 
     134           22 :    END SUBROUTINE topology_generate_molname
     135              : 
     136              : ! **************************************************************************************************
     137              : !> \brief Generates molnames: useful when the connectivity on file does not
     138              : !>        provide them
     139              : !> \param i ...
     140              : !> \param atom_bond_list ...
     141              : !> \param molname ...
     142              : !> \param id_molname ...
     143              : !> \author Teodoro Laino [tlaino] - University of Zurich 10.2008
     144              : ! **************************************************************************************************
     145        79132 :    RECURSIVE SUBROUTINE generate_molname_low(i, atom_bond_list, molname, id_molname)
     146              :       INTEGER, INTENT(IN)                                :: i
     147              :       TYPE(array1_list_type), DIMENSION(:)               :: atom_bond_list
     148              :       CHARACTER(LEN=default_string_length), INTENT(IN)   :: molname
     149              :       INTEGER, DIMENSION(:), INTENT(INOUT)               :: id_molname
     150              : 
     151              :       INTEGER                                            :: j, k
     152              : 
     153              :       IF (debug_this_module) THEN
     154              :          WRITE (*, *) "Entered with :", i
     155              :          WRITE (*, *) TRIM(molname)//": entering with i:", i, " full series to test:: ", atom_bond_list(i)%array1
     156              :          IF ((TRIM(id2str(id_molname(i))) /= "__UNDEF__") .AND. &
     157              :              (TRIM(id2str(id_molname(i))) /= TRIM(molname))) THEN
     158              :             WRITE (*, *) "Atom (", i, ") has already a molecular name assigned ! ("//TRIM(id2str(id_molname(i)))//")."
     159              :             WRITE (*, *) "New molecular name would be: ("//TRIM(molname)//")."
     160              :             CPABORT("Detecting something wrong in the molecular setup!")
     161              :          END IF
     162              :       END IF
     163        79132 :       id_molname(i) = str2id(molname)
     164       194494 :       DO j = 1, SIZE(atom_bond_list(i)%array1)
     165       115362 :          k = atom_bond_list(i)%array1(j)
     166              :          IF (debug_this_module) WRITE (*, *) "entering with i:", i, "testing :", k
     167       115362 :          IF (k == -1) CYCLE
     168        57178 :          atom_bond_list(i)%array1(j) = -1
     169       128560 :          WHERE (atom_bond_list(k)%array1 == i) atom_bond_list(k)%array1 = -1
     170       194494 :          CALL generate_molname_low(k, atom_bond_list, molname, id_molname)
     171              :       END DO
     172        79132 :    END SUBROUTINE generate_molname_low
     173              : 
     174              : ! **************************************************************************************************
     175              : !> \brief Use information from bond list to generate molecule. (ie clustering)
     176              : !> \param topology ...
     177              : !> \param qmmm ...
     178              : !> \param qmmm_env ...
     179              : !> \param subsys_section ...
     180              : ! **************************************************************************************************
     181        11404 :    SUBROUTINE topology_generate_molecule(topology, qmmm, qmmm_env, subsys_section)
     182              :       TYPE(topology_parameters_type), INTENT(INOUT)      :: topology
     183              :       LOGICAL, INTENT(in), OPTIONAL                      :: qmmm
     184              :       TYPE(qmmm_env_mm_type), OPTIONAL, POINTER          :: qmmm_env
     185              :       TYPE(section_vals_type), POINTER                   :: subsys_section
     186              : 
     187              :       CHARACTER(len=*), PARAMETER :: routineN = 'topology_generate_molecule'
     188              :       INTEGER, PARAMETER                                 :: nblock = 100
     189              : 
     190              :       INTEGER :: atom_in_kind, atom_in_mol, first, handle, handle2, i, iatm, iatom, iend, ifirst, &
     191              :          ilast, inum, istart, itype, iw, j, jump1, jump2, last, max_mol_num, mol_num, mol_res, &
     192              :          mol_typ, myind, N, natom, nlocl, ntype, resid
     193        11404 :       INTEGER, DIMENSION(:), POINTER                     :: qm_atom_index, wrk1, wrk2
     194              :       LOGICAL                                            :: do_again, found, my_qmmm
     195        11404 :       TYPE(array1_list_type), ALLOCATABLE, DIMENSION(:)  :: atom_bond_list
     196              :       TYPE(atom_info_type), POINTER                      :: atom_info
     197              :       TYPE(connectivity_info_type), POINTER              :: conn_info
     198              :       TYPE(cp_logger_type), POINTER                      :: logger
     199              : 
     200        11404 :       NULLIFY (logger)
     201        22808 :       logger => cp_get_default_logger()
     202              :       iw = cp_print_key_unit_nr(logger, subsys_section, "PRINT%TOPOLOGY_INFO/UTIL_INFO", &
     203        11404 :                                 extension=".subsysLog")
     204        11404 :       CALL timeset(routineN, handle)
     205        11404 :       NULLIFY (qm_atom_index)
     206        11404 :       NULLIFY (wrk1)
     207        11404 :       NULLIFY (wrk2)
     208              : 
     209        11404 :       atom_info => topology%atom_info
     210        11404 :       conn_info => topology%conn_info
     211              :       !
     212              :       ! QM/MM coordinate_control
     213              :       !
     214        11404 :       my_qmmm = .FALSE.
     215        11404 :       IF (PRESENT(qmmm) .AND. PRESENT(qmmm_env)) my_qmmm = qmmm
     216              : 
     217        11404 :       natom = topology%natoms
     218        11404 :       IF (ASSOCIATED(atom_info%map_mol_typ)) DEALLOCATE (atom_info%map_mol_typ)
     219        34212 :       ALLOCATE (atom_info%map_mol_typ(natom))
     220              : 
     221        11404 :       IF (ASSOCIATED(atom_info%map_mol_num)) DEALLOCATE (atom_info%map_mol_num)
     222        22808 :       ALLOCATE (atom_info%map_mol_num(natom))
     223              : 
     224        11404 :       IF (ASSOCIATED(atom_info%map_mol_res)) DEALLOCATE (atom_info%map_mol_res)
     225        22808 :       ALLOCATE (atom_info%map_mol_res(natom))
     226              : 
     227              :       ! Initialisation
     228       776609 :       atom_info%map_mol_typ(:) = 0
     229       776609 :       atom_info%map_mol_num(:) = -1
     230       776609 :       atom_info%map_mol_res(:) = 1
     231              : 
     232              :       ! Parse the atom list to find the different molecule types and residues
     233        11404 :       ntype = 1
     234        11404 :       atom_info%map_mol_typ(1) = 1
     235        11404 :       resid = 1
     236        11404 :       CALL reallocate(wrk1, 1, nblock)
     237        11404 :       wrk1(1) = atom_info%id_molname(1)
     238       765205 :       DO iatom = 2, natom
     239       765205 :          IF (topology%conn_type == do_conn_off) THEN
     240              :             ! No connectivity: each atom becomes a molecule of its own molecule kind
     241        44894 :             ntype = ntype + 1
     242        44894 :             atom_info%map_mol_typ(iatom) = ntype
     243       708907 :          ELSE IF (topology%conn_type == do_conn_user) THEN
     244              :             ! User-defined connectivity: 5th column of COORD section or molecule
     245              :             ! or residue name in the case of PDB files
     246        29570 :             IF ((atom_info%id_molname(iatom) == atom_info%id_molname(iatom - 1)) .AND. &
     247              :                 (.NOT. MODULO(iatom, topology%natom_muc) == 1)) THEN
     248        28186 :                atom_info%map_mol_typ(iatom) = atom_info%map_mol_typ(iatom - 1)
     249        28186 :                IF (atom_info%id_resname(iatom) == atom_info%id_resname(iatom - 1)) THEN
     250        26940 :                   atom_info%map_mol_res(iatom) = atom_info%map_mol_res(iatom - 1)
     251              :                ELSE
     252         1246 :                   resid = resid + 1
     253         1246 :                   atom_info%map_mol_res(iatom) = resid
     254              :                END IF
     255              :             ELSE
     256              :                ! Check if the type is already known
     257         1384 :                found = .FALSE.
     258        19630 :                DO itype = 1, ntype
     259        19630 :                   IF (atom_info%id_molname(iatom) == wrk1(itype)) THEN
     260          998 :                      atom_info%map_mol_typ(iatom) = itype
     261              :                      found = .TRUE.
     262              :                      EXIT
     263              :                   END IF
     264              :                END DO
     265              :                IF (.NOT. found) THEN
     266          386 :                   ntype = ntype + 1
     267          386 :                   atom_info%map_mol_typ(iatom) = ntype
     268          386 :                   IF (ntype > SIZE(wrk1)) CALL reallocate(wrk1, 1, 2*SIZE(wrk1))
     269          386 :                   wrk1(ntype) = atom_info%id_molname(iatom)
     270              :                END IF
     271         1384 :                resid = resid + 1
     272         1384 :                atom_info%map_mol_res(iatom) = resid
     273              :             END IF
     274              :          ELSE
     275       679337 :             IF (atom_info%id_molname(iatom - 1) == atom_info%id_molname(iatom)) THEN
     276       593316 :                atom_info%map_mol_typ(iatom) = ntype
     277              :             ELSE
     278        86021 :                ntype = ntype + 1
     279        86021 :                atom_info%map_mol_typ(iatom) = ntype
     280              :             END IF
     281              :          END IF
     282              :       END DO
     283        11404 :       DEALLOCATE (wrk1)
     284              : 
     285        11404 :       IF (iw > 0) WRITE (iw, '(/,T2,A)') "Start of molecule generation"
     286              : 
     287              :       ! convert a simple list of bonds to a list of bonds per atom
     288              :       ! (each bond is present in the forward and backward direction)
     289       799417 :       ALLOCATE (atom_bond_list(natom))
     290       776609 :       DO I = 1, natom
     291       776609 :          ALLOCATE (atom_bond_list(I)%array1(0))
     292              :       END DO
     293        11404 :       N = 0
     294        11404 :       IF (ASSOCIATED(conn_info%bond_a)) N = SIZE(conn_info%bond_a)
     295        11404 :       CALL reorder_structure(atom_bond_list, conn_info%bond_a, conn_info%bond_b, N)
     296        11404 :       CALL find_molecule(atom_bond_list, atom_info%map_mol_num, atom_info%id_molname)
     297       776609 :       DO I = 1, natom
     298       776609 :          DEALLOCATE (atom_bond_list(I)%array1)
     299              :       END DO
     300        11404 :       DEALLOCATE (atom_bond_list)
     301        11404 :       IF (iw > 0) WRITE (iw, '(/,T2,A)') "End of molecule generation"
     302              : 
     303              :       ! Modify according map_mol_typ the array map_mol_num
     304        11404 :       IF (iw > 0) WRITE (iw, '(/,T2,A)') "Checking for non-continuous generated molecules"
     305              :       ! Check molecule number
     306        22808 :       ALLOCATE (wrk1(natom))
     307        22808 :       ALLOCATE (wrk2(natom))
     308      1553218 :       wrk1 = atom_info%map_mol_num
     309              : 
     310              :       IF (debug_this_module) THEN
     311              :          DO i = 1, natom
     312              :             WRITE (*, '(2I10)') i, atom_info%map_mol_num(i)
     313              :          END DO
     314              :       END IF
     315              : 
     316        11404 :       CALL sort(wrk1, natom, wrk2)
     317        11404 :       istart = 1
     318        11404 :       mol_typ = wrk1(istart)
     319       765205 :       DO i = 2, natom
     320       765205 :          IF (mol_typ /= wrk1(i)) THEN
     321       327790 :             iend = i - 1
     322      1063655 :             first = MINVAL(wrk2(istart:iend))
     323      1063655 :             last = MAXVAL(wrk2(istart:iend))
     324       327790 :             nlocl = last - first + 1
     325       327790 :             IF (iend - istart + 1 /= nlocl) THEN
     326              :                IF (debug_this_module) WRITE (*, *) iend, istart, iend - istart + 1, first, last, nlocl
     327              :                CALL cp_abort(__LOCATION__, &
     328              :                              "CP2K requires molecules to be contiguous and we have detected a non contiguous one!! "// &
     329              :                              "In particular a molecule defined from index ("//cp_to_string(first)//") to ("// &
     330              :                              cp_to_string(last)//") contains other molecules, not connected! "// &
     331              :                              "Too late at this stage everything should be already ordered! "// &
     332              :                              "If you have not yet employed the REORDERING keyword, please do so. "// &
     333            0 :                              "It may help to fix this issue.")
     334              :             END IF
     335       327790 :             istart = i
     336       327790 :             mol_typ = wrk1(istart)
     337              :          END IF
     338              :       END DO
     339        11404 :       iend = i - 1
     340        40744 :       first = MINVAL(wrk2(istart:iend))
     341        40744 :       last = MAXVAL(wrk2(istart:iend))
     342        11404 :       nlocl = last - first + 1
     343        11404 :       IF (iend - istart + 1 /= nlocl) THEN
     344              :          IF (debug_this_module) WRITE (*, *) iend, istart, iend - istart + 1, first, last, nlocl
     345              :          CALL cp_abort(__LOCATION__, &
     346              :                        "CP2K requires molecules to be contiguous and we have detected a non contiguous one!! "// &
     347              :                        "In particular a molecule defined from index ("//cp_to_string(first)//") to ("// &
     348              :                        cp_to_string(last)//") contains other molecules, not connected! "// &
     349              :                        "Too late at this stage everything should be already ordered! "// &
     350              :                        "If you have not yet employed the REORDERING keyword, please do so. "// &
     351            0 :                        "It may help to fix this issue.")
     352              :       END IF
     353        11404 :       DEALLOCATE (wrk1)
     354        11404 :       DEALLOCATE (wrk2)
     355        11404 :       IF (iw > 0) WRITE (iw, '(/,T2,A)') "End of check"
     356              : 
     357        11404 :       IF (iw > 0) WRITE (UNIT=iw, FMT="(/,T2,A)") "Start of renumbering molecules"
     358        11404 :       IF (topology%conn_type == do_conn_user) THEN
     359          170 :          mol_num = 1
     360          170 :          atom_info%map_mol_num(1) = 1
     361        29740 :          DO iatom = 2, natom
     362        29570 :             IF (atom_info%id_molname(iatom) /= atom_info%id_molname(iatom - 1)) THEN
     363              :                mol_num = 1
     364        29184 :             ELSE IF (atom_info%map_mol_res(iatom) /= atom_info%map_mol_res(iatom - 1)) THEN
     365         2244 :                mol_num = mol_num + 1
     366              :             END IF
     367        29740 :             atom_info%map_mol_num(iatom) = mol_num
     368              :          END DO
     369              :       ELSE
     370        11234 :          mol_typ = atom_info%map_mol_typ(1)
     371        11234 :          mol_num = atom_info%map_mol_num(1)
     372       735465 :          DO i = 2, natom
     373       724231 :             IF (atom_info%map_mol_typ(i) /= mol_typ) THEN
     374       130915 :                myind = atom_info%map_mol_num(i) - mol_num + 1
     375       130915 :                CPASSERT(myind /= atom_info%map_mol_num(i - 1))
     376       130915 :                mol_typ = atom_info%map_mol_typ(i)
     377       130915 :                mol_num = atom_info%map_mol_num(i)
     378              :             END IF
     379       735465 :             atom_info%map_mol_num(i) = atom_info%map_mol_num(i) - mol_num + 1
     380              :          END DO
     381              :       END IF
     382        11404 :       IF (iw > 0) WRITE (UNIT=iw, FMT="(/,T2,A)") "End of renumbering molecules"
     383              : 
     384              :       ! Optionally, use the residues as molecules
     385        11404 :       CALL timeset(routineN//"_PARA_RES", handle2)
     386        11404 :       IF (iw > 0) WRITE (UNIT=iw, FMT="(/,T2,A,L2)") "Starting PARA_RES: ", topology%para_res
     387        11404 :       IF (topology%para_res) THEN
     388        10672 :          IF (topology%conn_type == do_conn_user) THEN
     389           34 :             atom_info%id_molname(:) = atom_info%id_resname(:)
     390            6 :             ntype = 1
     391            6 :             atom_info%map_mol_typ(1) = 1
     392            6 :             mol_num = 1
     393            6 :             atom_info%map_mol_num(1) = 1
     394           28 :             DO iatom = 2, natom
     395           22 :                IF (atom_info%id_molname(iatom) /= atom_info%id_molname(iatom - 1)) THEN
     396            6 :                   ntype = ntype + 1
     397            6 :                   mol_num = 1
     398           16 :                ELSE IF (atom_info%map_mol_res(iatom) /= atom_info%map_mol_res(iatom - 1)) THEN
     399            0 :                   mol_num = mol_num + 1
     400              :                END IF
     401           22 :                atom_info%map_mol_typ(iatom) = ntype
     402           28 :                atom_info%map_mol_num(iatom) = mol_num
     403              :             END DO
     404              :          ELSE
     405        10666 :             mol_res = 1
     406        10666 :             mol_typ = atom_info%map_mol_typ(1)
     407        10666 :             mol_num = atom_info%map_mol_num(1)
     408        10666 :             atom_info%map_mol_res(1) = mol_res
     409       731469 :             DO i = 2, natom
     410       720803 :                IF ((atom_info%resid(i - 1) /= atom_info%resid(i)) .OR. &
     411              :                    (atom_info%id_resname(i - 1) /= atom_info%id_resname(i))) THEN
     412       226039 :                   mol_res = mol_res + 1
     413              :                END IF
     414       720803 :                IF ((atom_info%map_mol_typ(i) /= mol_typ) .OR. &
     415              :                    (atom_info%map_mol_num(i) /= mol_num)) THEN
     416       294920 :                   mol_typ = atom_info%map_mol_typ(i)
     417       294920 :                   mol_num = atom_info%map_mol_num(i)
     418       294920 :                   mol_res = 1
     419              :                END IF
     420       731469 :                atom_info%map_mol_res(i) = mol_res
     421              :             END DO
     422              :          END IF
     423              :       END IF
     424        11404 :       IF (iw > 0) WRITE (UNIT=iw, FMT="(/,T2,A)") "End of PARA_RES"
     425        11404 :       CALL timestop(handle2)
     426              : 
     427        11404 :       IF (iw > 0) THEN
     428         1559 :          DO iatom = 1, natom
     429         1532 :             WRITE (iw, '(4(1X,A,":",I0),2(1X,A,1X,A))') "iatom", iatom, &
     430         1532 :                "map_mol_typ", atom_info%map_mol_typ(iatom), &
     431         1532 :                "map_mol_num", atom_info%map_mol_num(iatom), &
     432         1532 :                "map_mol_res", atom_info%map_mol_res(iatom), &
     433         1532 :                "mol_name:", TRIM(id2str(atom_info%id_molname(iatom))), &
     434         3091 :                "res_name:", TRIM(id2str(atom_info%id_resname(iatom)))
     435              :          END DO
     436              :       END IF
     437              : 
     438        11404 :       IF (my_qmmm) THEN
     439          394 :          do_again = .FALSE.
     440          394 :          IF (iw > 0) WRITE (iw, *) "MAP_MOL_NUM ", atom_info%map_mol_num
     441          394 :          IF (iw > 0) WRITE (iw, *) "MAP_MOL_TYP ", atom_info%map_mol_typ
     442          394 :          IF (iw > 0) WRITE (iw, *) "MAP_MOL_RES ", atom_info%map_mol_res
     443         1182 :          ALLOCATE (qm_atom_index(SIZE(qmmm_env%qm_atom_index)))
     444         6572 :          qm_atom_index = qmmm_env%qm_atom_index
     445         3286 :          CPASSERT(ALL(qm_atom_index /= 0))
     446         1958 :          DO myind = 1, SIZE(qm_atom_index)
     447         1854 :             IF (qm_atom_index(myind) == 0) CYCLE
     448              :             CALL find_boundary(atom_info%map_mol_typ, natom, ifirst, ilast, &
     449          974 :                                atom_info%map_mol_typ(qm_atom_index(myind)))
     450              :             CALL find_boundary(atom_info%map_mol_typ, atom_info%map_mol_num, natom, ifirst, ilast, &
     451          974 :                                atom_info%map_mol_typ(qm_atom_index(myind)), atom_info%map_mol_num(qm_atom_index(myind)))
     452          974 :             IF (iw > 0) WRITE (iw, *) "qm fragment:: ifirst, ilast", ifirst, ilast
     453          974 :             CPASSERT(((ifirst /= 0) .OR. (ilast /= natom)))
     454        16314 :             DO iatm = ifirst, ilast
     455              :                atom_info%id_molname(iatm) = str2id(s2s("_QM_"// &
     456        15340 :                                                        TRIM(id2str(atom_info%id_molname(iatm)))))
     457        15340 :                IF (iw > 0) WRITE (iw, *) "QM Molecule name :: ", id2str(atom_info%id_molname(iatm))
     458       786952 :                WHERE (qm_atom_index == iatm) qm_atom_index = 0
     459              :             END DO
     460       466890 :             DO iatm = 1, ifirst - 1
     461     59902382 :                IF (ANY(qm_atom_index == iatm)) do_again = .TRUE.
     462              :             END DO
     463       626780 :             DO iatm = ilast + 1, natom
     464     62275092 :                IF (ANY(qm_atom_index == iatm)) do_again = .TRUE.
     465              :             END DO
     466          974 :             IF (iw > 0) WRITE (iw, *) " Another QM fragment? :: ", do_again
     467          974 :             IF (ifirst /= 1) THEN
     468          656 :                jump1 = atom_info%map_mol_typ(ifirst) - atom_info%map_mol_typ(ifirst - 1)
     469          656 :                CPASSERT(jump1 <= 1 .AND. jump1 >= 0)
     470          656 :                jump1 = ABS(jump1 - 1)
     471              :             ELSE
     472              :                jump1 = 0
     473              :             END IF
     474          974 :             IF (ilast /= natom) THEN
     475          878 :                jump2 = atom_info%map_mol_typ(ilast + 1) - atom_info%map_mol_typ(ilast)
     476          878 :                CPASSERT(jump2 <= 1 .AND. jump2 >= 0)
     477          878 :                jump2 = ABS(jump2 - 1)
     478              :             ELSE
     479              :                jump2 = 0
     480              :             END IF
     481              : 
     482              :             ! Changing mol_type consistently
     483       642120 :             DO iatm = ifirst, natom
     484       642120 :                atom_info%map_mol_typ(iatm) = atom_info%map_mol_typ(iatm) + jump1
     485              :             END DO
     486       626780 :             DO iatm = ilast + 1, natom
     487       626780 :                atom_info%map_mol_typ(iatm) = atom_info%map_mol_typ(iatm) + jump2
     488              :             END DO
     489          974 :             IF (jump1 == 1) THEN
     490          608 :                DO iatm = ifirst, ilast
     491          608 :                   atom_info%map_mol_num(iatm) = 1
     492              :                END DO
     493              :             END IF
     494              : 
     495          974 :             IF (jump2 == 1) THEN
     496          254 :                CALL find_boundary(atom_info%map_mol_typ, natom, first, last, atom_info%map_mol_typ(ilast + 1))
     497              :                CALL find_boundary(atom_info%map_mol_typ, atom_info%map_mol_num, natom, ifirst, ilast, &
     498          254 :                                   atom_info%map_mol_typ(ilast + 1), atom_info%map_mol_num(ilast + 1))
     499          254 :                atom_in_mol = ilast - ifirst + 1
     500          254 :                inum = 1
     501          254 :                DO iatm = first, last, atom_in_mol
     502       167580 :                   atom_info%map_mol_num(iatm:iatm + atom_in_mol - 1) = inum
     503        42224 :                   inum = inum + 1
     504              :                END DO
     505              :             END IF
     506              : 
     507         2052 :             IF (.NOT. do_again) EXIT
     508              :          END DO
     509          394 :          DEALLOCATE (qm_atom_index)
     510              : 
     511          394 :          IF (iw > 0) THEN
     512            0 :             WRITE (iw, *) "After the QM/MM Setup:"
     513            0 :             DO iatom = 1, natom
     514            0 :                WRITE (iw, *) "      iatom,map_mol_typ,map_mol_num ", iatom, &
     515            0 :                   atom_info%map_mol_typ(iatom), atom_info%map_mol_num(iatom)
     516              :             END DO
     517              :          END IF
     518              :       END IF
     519              :       !
     520              :       ! Further check : see if the number of atoms belonging to same molecule kinds
     521              :       !                 are equal
     522        11404 :       IF (iw > 0) THEN
     523           27 :          WRITE (iw, *) "SUMMARY:: Number of molecule kinds found:", ntype
     524         1559 :          ntype = MAXVAL(atom_info%map_mol_typ)
     525          460 :          DO i = 1, ntype
     526       154989 :             atom_in_kind = COUNT(atom_info%map_mol_typ == i)
     527          433 :             WRITE (iw, *) "Molecule kind:", i, " contains", atom_in_kind, " atoms"
     528          433 :             IF (atom_in_kind <= 1) CYCLE
     529           24 :             CALL find_boundary(atom_info%map_mol_typ, natom, first, last, i)
     530           24 :             WRITE (iw, *) "Boundary atoms:", first, last
     531           24 :             CPASSERT(last - first + 1 == atom_in_kind)
     532         1147 :             max_mol_num = MAXVAL(atom_info%map_mol_num(first:last))
     533           24 :             WRITE (iw, *) "Number of molecules of kind", i, "is ::", max_mol_num
     534           24 :             atom_in_mol = atom_in_kind/max_mol_num
     535           24 :             WRITE (iw, *) "Number of atoms per each molecule:", atom_in_mol
     536         1147 :             WRITE (iw, *) "MAP_MOL_TYP::", atom_info%map_mol_typ(first:last)
     537         1147 :             WRITE (iw, *) "MAP_MOL_NUM::", atom_info%map_mol_num(first:last)
     538         1147 :             WRITE (iw, *) "MAP_MOL_RES::", atom_info%map_mol_res(first:last)
     539              :             !
     540          195 :             DO j = 1, max_mol_num
     541        31706 :                IF (COUNT(atom_info%map_mol_num(first:last) == j) /= atom_in_mol) THEN
     542            0 :                   WRITE (iw, *) "molecule type:", i, "molecule num:", j, " has ", &
     543            0 :                      COUNT(atom_info%map_mol_num(first:last) == j), &
     544            0 :                      " atoms instead of ", atom_in_mol, " ."
     545              :                   CALL cp_abort(__LOCATION__, &
     546              :                                 "Two molecules of the same kind have "// &
     547            0 :                                 "been created with different numbers of atoms!")
     548              :                END IF
     549              :             END DO
     550              :          END DO
     551              :       END IF
     552              :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
     553        11404 :                                         "PRINT%TOPOLOGY_INFO/UTIL_INFO")
     554        11404 :       CALL timestop(handle)
     555        45616 :    END SUBROUTINE topology_generate_molecule
     556              : 
     557              : ! **************************************************************************************************
     558              : !> \brief Use info from periodic table and assumptions to generate bonds
     559              : !> \param topology ...
     560              : !> \param para_env ...
     561              : !> \param subsys_section ...
     562              : !> \author Teodoro Laino 09.2006
     563              : ! **************************************************************************************************
     564         9197 :    SUBROUTINE topology_generate_bond(topology, para_env, subsys_section)
     565              :       TYPE(topology_parameters_type), INTENT(INOUT)      :: topology
     566              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     567              :       TYPE(section_vals_type), POINTER                   :: subsys_section
     568              : 
     569              :       CHARACTER(len=*), PARAMETER :: routineN = 'topology_generate_bond'
     570              : 
     571              :       CHARACTER(LEN=2)                                   :: upper_sym_1
     572              :       INTEGER :: cbond, handle, handle2, i, iatm1, iatm2, iatom, ibond, idim, iw, j, jatom, k, &
     573              :          n_bonds, n_heavy_bonds, n_hydr_bonds, n_rep, natom, npairs, output_unit
     574         9197 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: bond_a, bond_b, list, map_nb
     575         9197 :       INTEGER, DIMENSION(:), POINTER                     :: isolated_atoms, tmp_v
     576              :       LOGICAL                                            :: connectivity_ok, explicit, print_info
     577         9197 :       LOGICAL, ALLOCATABLE, DIMENSION(:)                 :: h_list
     578              :       REAL(KIND=dp)                                      :: bondparm_factor, cell_v(3), dr(3), &
     579              :                                                             ksign, my_maxrad, r2, r2_min, rbond, &
     580              :                                                             rbond2, tmp
     581              :       REAL(KIND=dp), DIMENSION(1, 1)                     :: r_max, r_minsq
     582         9197 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: radius
     583         9197 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: pbc_coord
     584         9197 :       TYPE(array2_list_type), DIMENSION(:), POINTER      :: bond_list
     585              :       TYPE(atom_info_type), POINTER                      :: atom_info
     586         9197 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     587              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
     588              :       TYPE(connectivity_info_type), POINTER              :: conn_info
     589              :       TYPE(cp_logger_type), POINTER                      :: logger
     590              :       TYPE(fist_neighbor_type), POINTER                  :: nonbonded
     591         9197 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     592              :       TYPE(section_vals_type), POINTER                   :: bond_section, generate_section, &
     593              :                                                             isolated_section
     594              : 
     595         9197 :       NULLIFY (logger, particle_set, atomic_kind_set, nonbonded, bond_section, generate_section)
     596         9197 :       NULLIFY (isolated_atoms, tmp_v)
     597         9197 :       CALL timeset(routineN, handle)
     598         9197 :       logger => cp_get_default_logger()
     599         9197 :       output_unit = cp_logger_get_default_io_unit(logger)
     600              :       iw = cp_print_key_unit_nr(logger, subsys_section, "PRINT%TOPOLOGY_INFO/GENERATE_INFO", &
     601         9197 :                                 extension=".subsysLog")
     602              :       ! Get atoms that one considers isolated (like ions in solution)
     603         9197 :       ALLOCATE (isolated_atoms(0))
     604         9197 :       generate_section => section_vals_get_subs_vals(subsys_section, "TOPOLOGY%GENERATE")
     605         9197 :       isolated_section => section_vals_get_subs_vals(generate_section, "ISOLATED_ATOMS")
     606         9197 :       CALL section_vals_get(isolated_section, explicit=explicit)
     607         9197 :       IF (explicit) THEN
     608            8 :          CALL section_vals_val_get(isolated_section, "LIST", n_rep_val=n_rep)
     609           20 :          DO i = 1, n_rep
     610           12 :             CALL section_vals_val_get(isolated_section, "LIST", i_vals=tmp_v, i_rep_val=i)
     611           12 :             CALL reallocate(isolated_atoms, 1, SIZE(isolated_atoms) + SIZE(tmp_v))
     612          196 :             isolated_atoms(SIZE(isolated_atoms) - SIZE(tmp_v) + 1:SIZE(isolated_atoms)) = tmp_v
     613              :          END DO
     614              :       END IF
     615         9197 :       atom_info => topology%atom_info
     616         9197 :       conn_info => topology%conn_info
     617         9197 :       bondparm_factor = topology%bondparm_factor
     618         9197 :       cbond = 0
     619         9197 :       natom = topology%natoms
     620         9197 :       NULLIFY (radius)
     621              :       ! Allocate temporary arrays
     622        27591 :       ALLOCATE (radius(natom))
     623        27591 :       ALLOCATE (list(natom))
     624        18394 :       ALLOCATE (h_list(natom))
     625        27591 :       ALLOCATE (pbc_coord(3, natom))
     626         9197 :       h_list = .FALSE.
     627         9197 :       CALL timeset(TRIM(routineN)//"_1", handle2)
     628       236993 :       DO iatom = 1, natom
     629       227796 :          list(iatom) = iatom
     630       227796 :          upper_sym_1 = TRIM(id2str(atom_info%id_element(iatom)))
     631       227796 :          IF (topology%bondparm_type == do_bondparm_covalent) THEN
     632       227796 :             CALL get_ptable_info(symbol=upper_sym_1, covalent_radius=radius(iatom))
     633            0 :          ELSE IF (topology%bondparm_type == do_bondparm_vdw) THEN
     634            0 :             CALL get_ptable_info(symbol=upper_sym_1, vdw_radius=radius(iatom))
     635              :          ELSE
     636            0 :             CPABORT("Illegal bondparm_type")
     637              :          END IF
     638       227796 :          IF (upper_sym_1 == "H ") h_list(iatom) = .TRUE.
     639              :          ! isolated atoms? put the radius to 0.0_dp
     640       353672 :          IF (ANY(isolated_atoms == iatom)) radius(iatom) = 0.0_dp
     641       227796 :          radius(iatom) = cp_unit_to_cp2k(radius(iatom), "angstrom")
     642       227796 :          IF (iw > 0) WRITE (iw, '(T2,"GENERATE|",5X,A,T50,A5,T60,A,T69,F12.6)') &
     643         3186 :             "In topology_generate_bond :: iatom = ", upper_sym_1, &
     644        15569 :             "radius:", radius(iatom)
     645              :       END DO
     646         9197 :       CALL timestop(handle2)
     647         9197 :       CALL timeset(TRIM(routineN)//"_2", handle2)
     648              :       ! Initialize fake particle_set and atomic_kinds to generate the bond list
     649              :       ! using the neighboring list routine
     650        18394 :       ALLOCATE (atomic_kind_set(1))
     651         9197 :       CALL allocate_particle_set(particle_set, natom)
     652              :       !
     653       236993 :       my_maxrad = MAXVAL(radius)*2.0_dp
     654         9197 :       atomic_kind => atomic_kind_set(1)
     655              :       CALL set_atomic_kind(atomic_kind=atomic_kind, kind_number=1, &
     656         9197 :                            name="XXX", element_symbol="XXX", mass=0.0_dp, atom_list=list)
     657         9197 :       CALL section_vals_val_get(subsys_section, "TOPOLOGY%GENERATE%BONDLENGTH_MAX", r_val=tmp)
     658        27591 :       r_max = tmp
     659         9197 :       IF (my_maxrad*bondparm_factor > r_max(1, 1) .AND. (.NOT. topology%molname_generated)) THEN
     660            0 :          IF (output_unit > 0) THEN
     661              :             WRITE (output_unit, '(T2,"GENERATE|",A)') &
     662            0 :                " ERROR in connectivity generation!", &
     663            0 :                " The THRESHOLD to select possible bonds is larger than the max. bondlength", &
     664            0 :                " used to build the neighbors lists. Increase the BONDLENGTH_MAX parameter"
     665              :             WRITE (output_unit, '(T2,"GENERATE|",2(A,F11.6),A)') &
     666            0 :                " Present THRESHOLD (", my_maxrad*bondparm_factor, " )."// &
     667            0 :                " Present BONDLENGTH_MAX (", r_max(1, 1), " )"
     668              :          END IF
     669            0 :          CPABORT("Unable to generate connectivity")
     670              :       END IF
     671       236993 :       DO i = 1, natom
     672       227796 :          particle_set(i)%atomic_kind => atomic_kind_set(1)
     673       227796 :          particle_set(i)%r(1) = atom_info%r(1, i)
     674       227796 :          particle_set(i)%r(2) = atom_info%r(2, i)
     675       227796 :          particle_set(i)%r(3) = atom_info%r(3, i)
     676       920381 :          pbc_coord(:, i) = pbc(atom_info%r(:, i), topology%cell)
     677              :       END DO
     678         9197 :       CALL section_vals_val_get(subsys_section, "TOPOLOGY%GENERATE%BONDLENGTH_MIN", r_val=tmp)
     679        27591 :       r_minsq = tmp*tmp
     680         9197 :       CALL timestop(handle2)
     681         9197 :       CALL timeset(TRIM(routineN)//"_3", handle2)
     682              :       CALL build_fist_neighbor_lists(atomic_kind_set, particle_set, &
     683              :                                      cell=topology%cell, r_max=r_max, r_minsq=r_minsq, &
     684              :                                      ei_scale14=1.0_dp, vdw_scale14=1.0_dp, nonbonded=nonbonded, &
     685              :                                      para_env=para_env, build_from_scratch=.TRUE., geo_check=.TRUE., &
     686         9197 :                                      mm_section=generate_section)
     687         9197 :       IF (iw > 0) THEN
     688              :          WRITE (iw, '(T2,"GENERATE| Number of prescreened bonds (neighbors):",T71,I10)') &
     689            8 :             nonbonded%neighbor_kind_pairs(1)%npairs
     690              :       END IF
     691         9197 :       npairs = 0
     692       170668 :       DO i = 1, SIZE(nonbonded%neighbor_kind_pairs)
     693       170668 :          npairs = npairs + nonbonded%neighbor_kind_pairs(i)%npairs
     694              :       END DO
     695        26757 :       ALLOCATE (bond_a(npairs))
     696        17560 :       ALLOCATE (bond_b(npairs))
     697        17560 :       ALLOCATE (map_nb(npairs))
     698         9197 :       idim = 0
     699       170668 :       DO j = 1, SIZE(nonbonded%neighbor_kind_pairs)
     700      1345077 :          DO i = 1, nonbonded%neighbor_kind_pairs(j)%npairs
     701      1174409 :             idim = idim + 1
     702      1174409 :             bond_a(idim) = nonbonded%neighbor_kind_pairs(j)%list(1, i)
     703      1174409 :             bond_b(idim) = nonbonded%neighbor_kind_pairs(j)%list(2, i)
     704      1335880 :             map_nb(idim) = j
     705              :          END DO
     706              :       END DO
     707         9197 :       CALL timestop(handle2)
     708         9197 :       CALL timeset(TRIM(routineN)//"_4", handle2)
     709              :       ! We have a list of neighbors let's order the list w.r.t. the particle number
     710       255387 :       ALLOCATE (bond_list(natom))
     711       236993 :       DO I = 1, natom
     712       227796 :          ALLOCATE (bond_list(I)%array1(0))
     713       236993 :          ALLOCATE (bond_list(I)%array2(0))
     714              :       END DO
     715         9197 :       CALL reorder_structure(bond_list, bond_a, bond_b, map_nb, SIZE(bond_a))
     716         9197 :       DEALLOCATE (bond_a)
     717         9197 :       DEALLOCATE (bond_b)
     718         9197 :       DEALLOCATE (map_nb)
     719              :       ! Find the Real bonds in the system
     720              :       ! Let's start with heavy atoms.. hydrogens will be treated only later on...
     721              :       ! Heavy atoms loop
     722         9197 :       CALL reallocate(conn_info%bond_a, 1, 1)
     723         9197 :       CALL reallocate(conn_info%bond_b, 1, 1)
     724         9197 :       connectivity_ok = .FALSE.
     725              :       ! No need to check consistency between provided molecule name and
     726              :       ! generated connectivity since we overrided the molecule definition.
     727         9197 :       IF (topology%create_molecules) THEN
     728         9436 :          atom_info%id_molname = str2id(s2s("TO_DEFINE_LATER"))
     729              :          ! A real name assignment will then be performed in the reorder module..
     730              :       END IF
     731              :       ! It may happen that the connectivity created is fault for the missing
     732              :       ! of one bond.. this external loop ensures that everything was created
     733              :       ! fits exactly with the definition of molecules..
     734        18396 :       DO WHILE (.NOT. connectivity_ok)
     735         9199 :          n_heavy_bonds = 0
     736              :          n_bonds = 0
     737       238225 :          DO iatm1 = 1, natom
     738       229026 :             IF (h_list(iatm1)) CYCLE
     739      1177381 :             DO j = 1, SIZE(bond_list(iatm1)%array1)
     740      1053768 :                iatm2 = bond_list(iatm1)%array1(j)
     741      1053768 :                IF (atom_info%id_molname(iatm1) /= atom_info%id_molname(iatm2)) CYCLE
     742       683562 :                IF (h_list(iatm2) .OR. (iatm2 <= iatm1)) CYCLE
     743       139888 :                k = bond_list(iatm1)%array2(j)
     744       139888 :                ksign = SIGN(1.0_dp, REAL(k, KIND=dp))
     745       139888 :                k = ABS(k)
     746              :                cell_v = MATMUL(topology%cell%hmat, &
     747      2238208 :                                REAL(nonbonded%neighbor_kind_pairs(k)%cell_vector, KIND=dp))
     748       559552 :                dr = pbc_coord(:, iatm1) - pbc_coord(:, iatm2) - ksign*cell_v
     749       559552 :                r2 = DOT_PRODUCT(dr, dr)
     750       139888 :                IF (r2 <= r_minsq(1, 1)) THEN
     751              :                   CALL cp_abort(__LOCATION__, &
     752              :                                 "bond distance between atoms less then the smallest distance provided "// &
     753            0 :                                 "in input "//cp_to_string(tmp)//" [bohr]")
     754              :                END IF
     755              :                ! Screen isolated atoms
     756      1617502 :                IF ((ANY(isolated_atoms == iatm1)) .OR. (ANY(isolated_atoms == iatm2))) CYCLE
     757              : 
     758              :                ! Screen neighbors
     759       138424 :                IF (topology%bondparm_type == do_bondparm_covalent) THEN
     760       138424 :                   rbond = radius(iatm1) + radius(iatm2)
     761            0 :                ELSE IF (topology%bondparm_type == do_bondparm_vdw) THEN
     762            0 :                   rbond = MAX(radius(iatm1), radius(iatm2))
     763              :                END IF
     764       138424 :                rbond2 = rbond*rbond
     765       138424 :                rbond2 = rbond2*(bondparm_factor)**2
     766              :                !Test the distance to the sum of the covalent radius
     767       367450 :                IF (r2 <= rbond2) THEN
     768        18044 :                   n_heavy_bonds = n_heavy_bonds + 1
     769        18044 :                   CALL add_bonds_list(conn_info, iatm1, iatm2, n_heavy_bonds)
     770              :                END IF
     771              :             END DO
     772              :          END DO
     773         9199 :          n_hydr_bonds = 0
     774         9199 :          n_bonds = n_heavy_bonds
     775              :          ! Now check bonds formed by hydrogens...
     776              :          ! The hydrogen valence is 1 so we can choose the closest atom..
     777         9199 :          IF (output_unit > 0) WRITE (output_unit, *)
     778       238225 :          DO iatm1 = 1, natom
     779       229026 :             IF (.NOT. h_list(iatm1)) CYCLE
     780       114612 :             r2_min = HUGE(0.0_dp)
     781       114612 :             ibond = -1
     782       114612 :             print_info = .TRUE.
     783      1416226 :             DO j = 1, SIZE(bond_list(iatm1)%array1)
     784      1301614 :                iatm2 = bond_list(iatm1)%array1(j)
     785      1301614 :                print_info = .FALSE.
     786      1301614 :                IF (atom_info%id_molname(iatm1) /= atom_info%id_molname(iatm2)) CYCLE
     787      1202826 :                IF (h_list(iatm2) .AND. (iatm2 <= iatm1)) CYCLE
     788              :                ! Screen isolated atoms
     789     12228642 :                IF ((ANY(isolated_atoms == iatm1)) .OR. (ANY(isolated_atoms == iatm2))) CYCLE
     790              : 
     791       799594 :                k = bond_list(iatm1)%array2(j)
     792       799594 :                ksign = SIGN(1.0_dp, REAL(k, KIND=dp))
     793       799594 :                k = ABS(k)
     794              :                cell_v = MATMUL(topology%cell%hmat, &
     795     12793504 :                                REAL(nonbonded%neighbor_kind_pairs(k)%cell_vector, KIND=dp))
     796      3198376 :                dr = pbc_coord(:, iatm1) - pbc_coord(:, iatm2) - ksign*cell_v
     797      3198376 :                r2 = DOT_PRODUCT(dr, dr)
     798       799594 :                IF (r2 <= r_minsq(1, 1)) THEN
     799              :                   CALL cp_abort(__LOCATION__, &
     800              :                                 "bond distance between atoms less then the smallest distance provided "// &
     801            0 :                                 "in input "//cp_to_string(tmp)//" [bohr]")
     802              :                END IF
     803       914206 :                IF (r2 <= r2_min) THEN
     804       227442 :                   r2_min = r2
     805       227442 :                   ibond = iatm2
     806              :                END IF
     807              :             END DO
     808       123811 :             IF (ibond == -1) THEN
     809        15570 :                IF (output_unit > 0 .AND. print_info) THEN
     810              :                   WRITE (output_unit, '(T2,"GENERATE|",1X,A,I10,A)') &
     811          135 :                      "WARNING:: No connections detected for Hydrogen - Atom Nr:", iatm1, " !"
     812              :                END IF
     813              :             ELSE
     814        99042 :                n_hydr_bonds = n_hydr_bonds + 1
     815        99042 :                n_bonds = n_bonds + 1
     816        99042 :                CALL add_bonds_list(conn_info, MIN(iatm1, ibond), MAX(iatm1, ibond), n_bonds)
     817              :             END IF
     818              :          END DO
     819         9199 :          IF (output_unit > 0) THEN
     820              :             WRITE (output_unit, '(T2,"GENERATE|",1X,A,T71,I10)') &
     821         4701 :                " Preliminary Number of Bonds generated:", n_bonds
     822              :          END IF
     823              :          ! External defined bonds (useful for complex connectivity)
     824         9199 :          bond_section => section_vals_get_subs_vals(generate_section, "BOND")
     825              :          CALL connectivity_external_control(section=bond_section, &
     826              :                                             Iarray1=conn_info%bond_a, &
     827              :                                             Iarray2=conn_info%bond_b, &
     828              :                                             nvar=n_bonds, &
     829              :                                             topology=topology, &
     830         9199 :                                             output_unit=output_unit)
     831              :          ! Resize arrays to their proper size..
     832         9199 :          CALL reallocate(conn_info%bond_a, 1, n_bonds)
     833         9199 :          CALL reallocate(conn_info%bond_b, 1, n_bonds)
     834         9199 :          IF (topology%create_molecules) THEN
     835              :             ! Since we create molecule names we're not sure that all atoms are contiguous
     836              :             ! so we need to reorder them on the basis of the generated name
     837          314 :             IF (.NOT. topology%reorder_atom) THEN
     838          304 :                topology%reorder_atom = .TRUE.
     839          304 :                IF (output_unit > 0) WRITE (output_unit, '(T2,"GENERATE|",A)') &
     840          152 :                   " Molecules names have been generated. Now reordering particle set in order to have ", &
     841          304 :                   " atoms belonging to the same molecule in a sequential order."
     842              :             END IF
     843              :             connectivity_ok = .TRUE.
     844              :          ELSE
     845              :             ! Check created connectivity and possibly give the OK to proceed
     846              :             connectivity_ok = check_generate_mol(conn_info%bond_a, conn_info%bond_b, &
     847         8885 :                                                  atom_info, bondparm_factor, output_unit)
     848              :          END IF
     849        18396 :          IF (my_maxrad*bondparm_factor > r_max(1, 1) .AND. (.NOT. topology%molname_generated)) THEN
     850            0 :             IF (output_unit > 0) THEN
     851              :                WRITE (output_unit, '(T2,"GENERATE|",A)') &
     852            0 :                   " ERROR in connectivity generation!", &
     853            0 :                   " The THRESHOLD to select possible bonds is bigger than the MAX bondlength", &
     854            0 :                   " used to build the neighbors lists. Increase the BONDLENGTH_MAX patameter"
     855              :                WRITE (output_unit, '(T2,"GENERATE|",2(A,F11.6),A)') &
     856            0 :                   " Present THRESHOLD (", my_maxrad*bondparm_factor, " )."// &
     857            0 :                   " Present BONDLENGTH_MAX (", r_max(1, 1), " )"
     858              :             END IF
     859            0 :             CPABORT("Unable to generate connectivity")
     860              :          END IF
     861              :       END DO
     862         9197 :       IF (connectivity_ok .AND. (output_unit > 0)) THEN
     863              :          WRITE (output_unit, '(T2,"GENERATE|",A)') &
     864         4700 :             "  Achieved consistency in connectivity generation."
     865              :       END IF
     866         9197 :       CALL fist_neighbor_deallocate(nonbonded)
     867         9197 :       CALL timestop(handle2)
     868         9197 :       CALL timeset(TRIM(routineN)//"_6", handle2)
     869              :       ! Deallocate temporary working arrays
     870       236993 :       DO I = 1, natom
     871       227796 :          DEALLOCATE (bond_list(I)%array1)
     872       236993 :          DEALLOCATE (bond_list(I)%array2)
     873              :       END DO
     874         9197 :       DEALLOCATE (bond_list)
     875         9197 :       DEALLOCATE (pbc_coord)
     876         9197 :       DEALLOCATE (radius)
     877         9197 :       DEALLOCATE (list)
     878         9197 :       CALL deallocate_particle_set(particle_set)
     879         9197 :       CALL deallocate_atomic_kind_set(atomic_kind_set)
     880              :       !
     881         9197 :       CALL timestop(handle2)
     882         9197 :       IF (output_unit > 0 .AND. n_bonds > 0) THEN
     883         1182 :          WRITE (output_unit, '(T2,"GENERATE|",1X,A,T71,I10)') " Number of Bonds generated:", &
     884         2364 :             n_bonds
     885              :       END IF
     886         9197 :       CALL timeset(TRIM(routineN)//"_7", handle2)
     887              :       ! If PARA_RES then activate RESIDUES
     888         9197 :       CALL reallocate(conn_info%c_bond_a, 1, 0)
     889         9197 :       CALL reallocate(conn_info%c_bond_b, 1, 0)
     890         9197 :       IF (topology%para_res) THEN
     891       125249 :          DO ibond = 1, SIZE(conn_info%bond_a)
     892       116052 :             iatom = conn_info%bond_a(ibond)
     893       116052 :             jatom = conn_info%bond_b(ibond)
     894              :             IF ((atom_info%id_molname(iatom) /= atom_info%id_molname(jatom)) .OR. &
     895       116052 :                 (atom_info%resid(iatom) /= atom_info%resid(jatom)) .OR. &
     896         9197 :                 (atom_info%id_resname(iatom) /= atom_info%id_resname(jatom))) THEN
     897         7214 :                IF (iw > 0) WRITE (iw, *) "      PARA_RES, bond between molecules atom ", &
     898            4 :                   iatom, jatom
     899         7212 :                cbond = cbond + 1
     900         7212 :                CALL reallocate(conn_info%c_bond_a, 1, cbond)
     901         7212 :                CALL reallocate(conn_info%c_bond_b, 1, cbond)
     902         7212 :                conn_info%c_bond_a(cbond) = iatom
     903         7212 :                conn_info%c_bond_b(cbond) = jatom
     904              :             ELSE
     905              :                IF (atom_info%id_molname(iatom) /= atom_info%id_molname(jatom)) THEN
     906              :                   CPABORT("Bonds between different molecule types?")
     907              :                END IF
     908              :             END IF
     909              :          END DO
     910              :       END IF
     911         9197 :       CALL timestop(handle2)
     912         9197 :       DEALLOCATE (isolated_atoms)
     913         9197 :       CALL timestop(handle)
     914              :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
     915         9197 :                                         "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
     916       101167 :    END SUBROUTINE topology_generate_bond
     917              : 
     918              : ! **************************************************************************************************
     919              : !> \brief Performs a check on the generated connectivity
     920              : !> \param bond_a ...
     921              : !> \param bond_b ...
     922              : !> \param atom_info ...
     923              : !> \param bondparm_factor ...
     924              : !> \param output_unit ...
     925              : !> \return ...
     926              : !> \author Teodoro Laino 09.2006
     927              : ! **************************************************************************************************
     928         8885 :    FUNCTION check_generate_mol(bond_a, bond_b, atom_info, bondparm_factor, output_unit) &
     929              :       RESULT(conn_ok)
     930              :       INTEGER, DIMENSION(:), POINTER                     :: bond_a, bond_b
     931              :       TYPE(atom_info_type), POINTER                      :: atom_info
     932              :       REAL(KIND=dp), INTENT(INOUT)                       :: bondparm_factor
     933              :       INTEGER, INTENT(IN)                                :: output_unit
     934              :       LOGICAL                                            :: conn_ok
     935              : 
     936              :       CHARACTER(len=*), PARAMETER :: routineN = 'check_generate_mol'
     937              : 
     938              :       CHARACTER(LEN=10)                                  :: ctmp1, ctmp2, ctmp3
     939              :       INTEGER                                            :: handle, i, idim, itype, j, mol_natom, &
     940              :                                                             natom, nsize
     941         8885 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: mol_info_tmp
     942         8885 :       INTEGER, DIMENSION(:), POINTER                     :: mol_map, mol_map_o, wrk
     943         8885 :       INTEGER, DIMENSION(:, :), POINTER                  :: mol_info
     944         8885 :       LOGICAL, DIMENSION(:), POINTER                     :: icheck
     945         8885 :       TYPE(array1_list_type), DIMENSION(:), POINTER      :: bond_list
     946              : 
     947         8885 :       CALL timeset(routineN, handle)
     948         8885 :       conn_ok = .TRUE.
     949         8885 :       natom = SIZE(atom_info%id_atmname)
     950       246559 :       ALLOCATE (bond_list(natom))
     951       228789 :       DO I = 1, natom
     952       228789 :          ALLOCATE (bond_list(I)%array1(0))
     953              :       END DO
     954         8885 :       CALL reorder_structure(bond_list, bond_a, bond_b, SIZE(bond_a))
     955        26655 :       ALLOCATE (mol_map(natom))
     956        17770 :       ALLOCATE (mol_map_o(natom))
     957        17770 :       ALLOCATE (wrk(natom))
     958              : 
     959       228789 :       DO i = 1, natom
     960       228789 :          mol_map(i) = atom_info%id_molname(i)
     961              :       END DO
     962       448693 :       mol_map_o = mol_map
     963              : 
     964         8885 :       CALL sort(mol_map, natom, wrk)
     965              :       !
     966              :       ! mol(i,1) : stores id of the molecule
     967              :       ! mol(i,2) : stores the total number of atoms forming that kind of molecule
     968              :       ! mol(i,3) : contains the number of molecules generated for that kind
     969              :       ! mol(i,4) : contains the number of atoms forming one molecule of that kind
     970              :       ! Connectivity will be considered correct only if for each i:
     971              :       !
     972              :       !               mol(i,2) = mol(i,3)*mol(i,4)
     973              :       !
     974              :       ! If not, very probably, a bond is missing increase bondparm by 10% and let's
     975              :       ! check if the newest connectivity is bug free..
     976              :       !
     977              : 
     978        26655 :       ALLOCATE (mol_info_tmp(natom, 2))
     979              : 
     980         8885 :       itype = mol_map(1)
     981         8885 :       nsize = 1
     982         8885 :       idim = 1
     983         8885 :       mol_info_tmp(1, 1) = itype
     984       219904 :       DO i = 2, natom
     985       219904 :          IF (mol_map(i) /= itype) THEN
     986        60147 :             nsize = nsize + 1
     987        60147 :             itype = mol_map(i)
     988        60147 :             mol_info_tmp(nsize, 1) = itype
     989        60147 :             mol_info_tmp(nsize - 1, 2) = idim
     990        60147 :             idim = 1
     991              :          ELSE
     992       150872 :             idim = idim + 1
     993              :          END IF
     994              :       END DO
     995         8885 :       mol_info_tmp(nsize, 2) = idim
     996              : 
     997        26655 :       ALLOCATE (mol_info(nsize, 4))
     998       164719 :       mol_info(1:nsize, 1:2) = mol_info_tmp(1:nsize, 1:2)
     999         8885 :       DEALLOCATE (mol_info_tmp)
    1000              : 
    1001        77917 :       DO i = 1, nsize
    1002        69032 :          mol_info(i, 3) = 0
    1003        77917 :          mol_info(i, 4) = 0
    1004              :       END DO
    1005              :       !
    1006        17770 :       ALLOCATE (icheck(natom))
    1007       228789 :       icheck = .FALSE.
    1008       228723 :       DO i = 1, natom
    1009       219840 :          IF (icheck(i)) CYCLE
    1010       112794 :          itype = mol_map_o(i)
    1011       112794 :          mol_natom = 0
    1012       112794 :          CALL give_back_molecule(icheck, bond_list, i, mol_natom, mol_map_o, mol_map_o(i))
    1013     13781513 :          DO j = 1, SIZE(mol_info)
    1014     13555925 :             IF (itype == mol_info(j, 1)) EXIT
    1015              :          END DO
    1016       112794 :          mol_info(j, 3) = mol_info(j, 3) + 1
    1017       112794 :          IF (mol_info(j, 4) == 0) mol_info(j, 4) = mol_natom
    1018       121678 :          IF (mol_info(j, 4) /= mol_natom) THEN
    1019              :             ! Two same molecules have been found with different number
    1020              :             ! of atoms. This usually indicates a missing bond in the
    1021              :             ! generated connectivity
    1022              :             ! Set connectivity to .false. EXIT and increase bondparm_factor by 1.05
    1023            2 :             conn_ok = .FALSE.
    1024            2 :             bondparm_factor = bondparm_factor*1.05_dp
    1025            2 :             IF (output_unit < 0) EXIT
    1026            1 :             WRITE (output_unit, '(/,T2,"GENERATE|",A)') " WARNING in connectivity generation!"
    1027              :             WRITE (output_unit, '(T2,"GENERATE|",A)') &
    1028              :                ' Two molecules/residues named ('//TRIM(id2str(itype))//') have different '// &
    1029            1 :                ' number of atoms.'
    1030            1 :             CALL integer_to_string(i, ctmp1)
    1031            1 :             CALL integer_to_string(mol_natom, ctmp2)
    1032            1 :             CALL integer_to_string(mol_info(j, 4), ctmp3)
    1033              :             WRITE (output_unit, '(T2,"GENERATE|",A)') ' Molecule starting at position ('// &
    1034              :                TRIM(ctmp1)//') has Nr. <'//TRIM(ctmp2)// &
    1035            1 :                '> of atoms.', ' while the other same molecules have Nr. <'// &
    1036            2 :                TRIM(ctmp3)//'> of atoms!'
    1037              :             WRITE (output_unit, '(T2,"GENERATE|",A)') &
    1038            1 :                ' Increasing bondparm_factor by 1.05.. An error was found in the generated', &
    1039            2 :                ' connectivity. Retry...'
    1040              :             WRITE (output_unit, '(T2,"GENERATE|",A,F11.6,A,/)') &
    1041            1 :                " Present value of BONDPARM_FACTOR (", bondparm_factor, " )."
    1042            1 :             EXIT
    1043              :          END IF
    1044              :       END DO
    1045              : 
    1046         8885 :       DEALLOCATE (icheck)
    1047         8885 :       DEALLOCATE (mol_info)
    1048         8885 :       DEALLOCATE (mol_map)
    1049         8885 :       DEALLOCATE (mol_map_o)
    1050         8885 :       DEALLOCATE (wrk)
    1051       228789 :       DO I = 1, natom
    1052       228789 :          DEALLOCATE (bond_list(I)%array1)
    1053              :       END DO
    1054         8885 :       DEALLOCATE (bond_list)
    1055         8885 :       CALL timestop(handle)
    1056         8885 :    END FUNCTION check_generate_mol
    1057              : 
    1058              : ! **************************************************************************************************
    1059              : !> \brief Add/Remove a bond to the generated list
    1060              : !>      Particularly useful for system with complex connectivity
    1061              : !> \param section ...
    1062              : !> \param Iarray1 ...
    1063              : !> \param Iarray2 ...
    1064              : !> \param Iarray3 ...
    1065              : !> \param Iarray4 ...
    1066              : !> \param nvar ...
    1067              : !> \param topology ...
    1068              : !> \param output_unit ...
    1069              : !> \param is_impr ...
    1070              : !> \author Teodoro Laino 09.2006
    1071              : ! **************************************************************************************************
    1072        29942 :    SUBROUTINE connectivity_external_control(section, Iarray1, Iarray2, Iarray3, Iarray4, nvar, &
    1073              :                                             topology, output_unit, is_impr)
    1074              :       TYPE(section_vals_type), POINTER                   :: section
    1075              :       INTEGER, DIMENSION(:), POINTER                     :: Iarray1, Iarray2
    1076              :       INTEGER, DIMENSION(:), OPTIONAL, POINTER           :: Iarray3, Iarray4
    1077              :       INTEGER, INTENT(INOUT)                             :: nvar
    1078              :       TYPE(topology_parameters_type), INTENT(INOUT)      :: topology
    1079              :       INTEGER, INTENT(IN)                                :: output_unit
    1080              :       LOGICAL, INTENT(IN), OPTIONAL                      :: is_impr
    1081              : 
    1082              :       CHARACTER(LEN=8)                                   :: fmt
    1083              :       INTEGER                                            :: do_action, do_it, i, j, k, n_rep, &
    1084              :                                                             n_rep_val, natom, new_size, nsize
    1085        14971 :       INTEGER, DIMENSION(:), POINTER                     :: atlist, Ilist1, Ilist2, Ilist3, Ilist4
    1086              :       LOGICAL                                            :: explicit, ip3, ip4
    1087              : 
    1088        14971 :       natom = topology%natoms
    1089              :       ! Preliminary sort of arrays
    1090        14971 :       ip3 = PRESENT(Iarray3)
    1091        14971 :       ip4 = PRESENT(Iarray4)
    1092        14971 :       nsize = 2
    1093         5772 :       IF (ip3) nsize = nsize + 1
    1094        14971 :       IF (ip3 .AND. ip4) nsize = nsize + 1
    1095              :       ! Put the lists always in the canonical order
    1096        14971 :       CALL reorder_list_array(Iarray1, Iarray2, Iarray3, Iarray4, nsize, nvar)
    1097              :       ! Go on with external control
    1098        14971 :       CALL section_vals_get(section, explicit=explicit, n_repetition=n_rep)
    1099        14971 :       IF (explicit) THEN
    1100           30 :          NULLIFY (Ilist1, Ilist2, Ilist3, Ilist4, atlist)
    1101           88 :          ALLOCATE (Ilist1(nvar))
    1102           58 :          ALLOCATE (Ilist2(nvar))
    1103         2702 :          Ilist1 = Iarray1(1:nvar)
    1104         2702 :          Ilist2 = Iarray2(1:nvar)
    1105           10 :          SELECT CASE (nsize)
    1106              :          CASE (2) !do nothing
    1107              :          CASE (3)
    1108           20 :             ALLOCATE (Ilist3(nvar))
    1109          706 :             Ilist3 = Iarray3(1:nvar)
    1110              :          CASE (4)
    1111           24 :             ALLOCATE (Ilist3(nvar))
    1112           24 :             ALLOCATE (Ilist4(nvar))
    1113          828 :             Ilist3 = Iarray3(1:nvar)
    1114          828 :             Ilist4 = Iarray4(1:nvar)
    1115              :          CASE DEFAULT
    1116              :             ! Should never reach this point
    1117           30 :             CPABORT("Only 2, 3, 4 are supported as the value of nsize")
    1118              :          END SELECT
    1119           30 :          CALL list_canonical_order(Ilist1, Ilist2, Ilist3, Ilist4, nsize, is_impr)
    1120              :          !
    1121           98 :          DO i = 1, n_rep
    1122           68 :             CALL section_vals_val_get(section, "ATOMS", i_rep_section=i, n_rep_val=n_rep_val)
    1123              :             CALL section_vals_val_get(section, "_SECTION_PARAMETERS_", i_rep_section=i, &
    1124           68 :                                       i_val=do_action)
    1125              :             !
    1126          180 :             DO j = 1, n_rep_val
    1127              :                CALL section_vals_val_get(section, "ATOMS", i_rep_section=i, i_rep_val=j, &
    1128           82 :                                          i_vals=atlist)
    1129           82 :                CPASSERT(SIZE(atlist) == nsize)
    1130           82 :                CALL integer_to_string(nsize - 1, fmt)
    1131              :                CALL check_element_list(do_it, do_action, atlist, Ilist1, Ilist2, Ilist3, Ilist4, &
    1132           82 :                                        is_impr)
    1133          150 :                IF (do_action == do_add) THEN
    1134              :                   ! Add to the element to the list
    1135           42 :                   IF (do_it > 0) THEN
    1136           26 :                      nvar = nvar + 1
    1137           26 :                      IF (output_unit > 0) THEN
    1138              :                         WRITE (output_unit, '(T2,"ADD|",1X,A,I6,'//TRIM(fmt)//'(A,I6),A,T64,A,I6)') &
    1139           13 :                            "element (", &
    1140           48 :                            atlist(1), (",", atlist(k), k=2, nsize), ") added.", " NEW size::", nvar
    1141              :                      END IF
    1142           26 :                      IF (nvar > SIZE(Iarray1)) THEN
    1143            2 :                         new_size = INT(5 + 1.2*nvar)
    1144            2 :                         CALL reallocate(Iarray1, 1, new_size)
    1145            2 :                         CALL reallocate(Iarray2, 1, new_size)
    1146            0 :                         SELECT CASE (nsize)
    1147              :                         CASE (3)
    1148            0 :                            CALL reallocate(Iarray3, 1, new_size)
    1149              :                         CASE (4)
    1150            0 :                            CALL reallocate(Iarray3, 1, new_size)
    1151            2 :                            CALL reallocate(Iarray4, 1, new_size)
    1152              :                         END SELECT
    1153              :                      END IF
    1154              :                      ! Using Ilist instead of atlist the canonical order is preserved..
    1155          428 :                      Iarray1(do_it + 1:nvar) = Iarray1(do_it:nvar - 1)
    1156          428 :                      Iarray2(do_it + 1:nvar) = Iarray2(do_it:nvar - 1)
    1157           26 :                      Iarray1(do_it) = Ilist1(do_it)
    1158           26 :                      Iarray2(do_it) = Ilist2(do_it)
    1159            2 :                      SELECT CASE (nsize)
    1160              :                      CASE (3)
    1161           86 :                         Iarray3(do_it + 1:nvar) = Iarray3(do_it:nvar - 1)
    1162            2 :                         Iarray3(do_it) = Ilist3(do_it)
    1163              :                      CASE (4)
    1164          230 :                         Iarray3(do_it + 1:nvar) = Iarray3(do_it:nvar - 1)
    1165          230 :                         Iarray4(do_it + 1:nvar) = Iarray4(do_it:nvar - 1)
    1166            8 :                         Iarray3(do_it) = Ilist3(do_it)
    1167           34 :                         Iarray4(do_it) = Ilist4(do_it)
    1168              :                      END SELECT
    1169              :                   ELSE
    1170           16 :                      IF (output_unit > 0) THEN
    1171              :                         WRITE (output_unit, '(T2,"ADD|",1X,A,I6,'//TRIM(fmt)//'(A,I6),A,T80,A)') &
    1172            8 :                            "element (", &
    1173           30 :                            atlist(1), (",", atlist(k), k=2, nsize), ") already found.", "X"
    1174              :                      END IF
    1175              :                   END IF
    1176              :                ELSE
    1177              :                   ! Remove element from the list
    1178           40 :                   IF (do_it > 0) THEN
    1179           34 :                      nvar = nvar - 1
    1180           34 :                      IF (output_unit > 0) THEN
    1181              :                         WRITE (output_unit, '(T2,"RMV|",1X,A,I6,'//TRIM(fmt)//'(A,I6),A,T64,A,I6)') &
    1182           17 :                            "element (", &
    1183           73 :                            atlist(1), (",", atlist(k), k=2, nsize), ") removed.", " NEW size::", nvar
    1184              :                      END IF
    1185          506 :                      Iarray1(do_it:nvar) = Iarray1(do_it + 1:nvar + 1)
    1186          506 :                      Iarray2(do_it:nvar) = Iarray2(do_it + 1:nvar + 1)
    1187           34 :                      Iarray1(nvar + 1) = -HUGE(0)
    1188           34 :                      Iarray2(nvar + 1) = -HUGE(0)
    1189           16 :                      SELECT CASE (nsize)
    1190              :                      CASE (3)
    1191          260 :                         Iarray3(do_it:nvar) = Iarray3(do_it + 1:nvar + 1)
    1192           16 :                         Iarray3(nvar + 1) = -HUGE(0)
    1193              :                      CASE (4)
    1194          146 :                         Iarray3(do_it:nvar) = Iarray3(do_it + 1:nvar + 1)
    1195          146 :                         Iarray4(do_it:nvar) = Iarray4(do_it + 1:nvar + 1)
    1196           14 :                         Iarray3(nvar + 1) = -HUGE(0)
    1197           48 :                         Iarray4(nvar + 1) = -HUGE(0)
    1198              :                      END SELECT
    1199              :                   ELSE
    1200            6 :                      IF (output_unit > 0) THEN
    1201              :                         WRITE (output_unit, '(T2,"RMV|",1X,A,I6,'//TRIM(fmt)//'(A,I6),A,T80,A)') &
    1202            3 :                            "element (", &
    1203           10 :                            atlist(1), (",", atlist(k), k=2, nsize), ") not found.", "X"
    1204              :                      END IF
    1205              :                   END IF
    1206              :                END IF
    1207              : 
    1208              :             END DO
    1209              :          END DO
    1210           30 :          DEALLOCATE (Ilist1)
    1211           30 :          DEALLOCATE (Ilist2)
    1212           10 :          SELECT CASE (nsize)
    1213              :          CASE (2) ! do nothing
    1214              :          CASE (3)
    1215           10 :             DEALLOCATE (Ilist3)
    1216              :          CASE (4)
    1217           12 :             DEALLOCATE (Ilist3)
    1218           12 :             DEALLOCATE (Ilist4)
    1219              :          CASE DEFAULT
    1220              :             ! Should never reach this point
    1221           30 :             CPABORT("Only 2, 3, 4 are supported as the value of nsize")
    1222              :          END SELECT
    1223              :       END IF
    1224        14971 :    END SUBROUTINE connectivity_external_control
    1225              : 
    1226              : ! **************************************************************************************************
    1227              : !> \brief Orders list in the canonical order: the extrema of the list are such
    1228              : !>      that the first extrema is always smaller or equal to the last extrema.
    1229              : !> \param Ilist1 ...
    1230              : !> \param Ilist2 ...
    1231              : !> \param Ilist3 ...
    1232              : !> \param Ilist4 ...
    1233              : !> \param nsize ...
    1234              : !> \param is_impr ...
    1235              : !> \author Teodoro Laino 09.2006
    1236              : ! **************************************************************************************************
    1237           30 :    SUBROUTINE list_canonical_order(Ilist1, Ilist2, Ilist3, Ilist4, nsize, is_impr)
    1238              :       INTEGER, DIMENSION(:), POINTER                     :: Ilist1, Ilist2
    1239              :       INTEGER, DIMENSION(:), OPTIONAL, POINTER           :: Ilist3, Ilist4
    1240              :       INTEGER, INTENT(IN)                                :: nsize
    1241              :       LOGICAL, INTENT(IN), OPTIONAL                      :: is_impr
    1242              : 
    1243              :       INTEGER                                            :: i, ss(3), tmp1, tmp2, tmp3, tt(3)
    1244              :       LOGICAL                                            :: do_impr
    1245              : 
    1246           30 :       do_impr = .FALSE.
    1247           30 :       IF (PRESENT(is_impr)) do_impr = is_impr
    1248           38 :       SELECT CASE (nsize)
    1249              :       CASE (2)
    1250          588 :          DO i = 1, SIZE(Ilist1)
    1251          580 :             tmp1 = Ilist1(i)
    1252          580 :             tmp2 = Ilist2(i)
    1253          580 :             Ilist1(i) = MIN(tmp1, tmp2)
    1254          588 :             Ilist2(i) = MAX(tmp1, tmp2)
    1255              :          END DO
    1256              :       CASE (3)
    1257          358 :          DO i = 1, SIZE(Ilist1)
    1258          348 :             tmp1 = Ilist1(i)
    1259          348 :             tmp2 = Ilist3(i)
    1260          348 :             Ilist1(i) = MIN(tmp1, tmp2)
    1261          358 :             Ilist3(i) = MAX(tmp1, tmp2)
    1262              :          END DO
    1263              :       CASE (4)
    1264          438 :          DO i = 1, SIZE(Ilist1)
    1265          420 :             IF (.NOT. do_impr) THEN
    1266          372 :                tmp1 = Ilist1(i)
    1267          372 :                tmp2 = Ilist4(i)
    1268          372 :                Ilist1(i) = MIN(tmp1, tmp2)
    1269          372 :                IF (Ilist1(i) == tmp2) THEN
    1270            0 :                   tmp3 = Ilist3(i)
    1271            0 :                   Ilist3(i) = Ilist2(i)
    1272            0 :                   Ilist2(i) = tmp3
    1273              :                END IF
    1274          372 :                Ilist4(i) = MAX(tmp1, tmp2)
    1275              :             ELSE
    1276           36 :                tt(1) = Ilist2(i)
    1277           36 :                tt(2) = Ilist3(i)
    1278           36 :                tt(3) = Ilist4(i)
    1279           36 :                CALL sort(tt, 3, ss)
    1280           36 :                Ilist2(i) = tt(1)
    1281           36 :                Ilist3(i) = tt(2)
    1282           36 :                Ilist4(i) = tt(3)
    1283              :             END IF
    1284              :          END DO
    1285              :       END SELECT
    1286              : 
    1287           30 :    END SUBROUTINE list_canonical_order
    1288              : 
    1289              : ! **************************************************************************************************
    1290              : !> \brief finds an element in the ordered list
    1291              : !> \param do_it ...
    1292              : !> \param do_action ...
    1293              : !> \param atlist ...
    1294              : !> \param Ilist1 ...
    1295              : !> \param Ilist2 ...
    1296              : !> \param Ilist3 ...
    1297              : !> \param Ilist4 ...
    1298              : !> \param is_impr ...
    1299              : !> \author Teodoro Laino 09.2006
    1300              : ! **************************************************************************************************
    1301           82 :    SUBROUTINE check_element_list(do_it, do_action, atlist, Ilist1, Ilist2, Ilist3, Ilist4, &
    1302              :                                  is_impr)
    1303              :       INTEGER, INTENT(OUT)                               :: do_it
    1304              :       INTEGER, INTENT(IN)                                :: do_action
    1305              :       INTEGER, DIMENSION(:), POINTER                     :: atlist, Ilist1, Ilist2
    1306              :       INTEGER, DIMENSION(:), OPTIONAL, POINTER           :: Ilist3, Ilist4
    1307              :       LOGICAL, INTENT(IN), OPTIONAL                      :: is_impr
    1308              : 
    1309              :       INTEGER                                            :: i, iend, istart, ndim, new_size, nsize, &
    1310              :                                                             ss(3), tmp1, tmp2, tmp3, tt(3)
    1311              :       INTEGER, DIMENSION(4)                              :: tmp
    1312              :       LOGICAL                                            :: do_impr, found
    1313              : 
    1314           82 :       do_impr = .FALSE.
    1315           82 :       IF (PRESENT(is_impr)) do_impr = is_impr
    1316           82 :       found = .FALSE.
    1317           82 :       nsize = SIZE(atlist)
    1318           82 :       ndim = SIZE(Ilist1)
    1319          322 :       DO i = 1, nsize
    1320          322 :          tmp(i) = atlist(i)
    1321              :       END DO
    1322           28 :       SELECT CASE (nsize)
    1323              :       CASE (2)
    1324           28 :          tmp1 = tmp(1)
    1325           28 :          tmp2 = tmp(2)
    1326           28 :          tmp(1) = MIN(tmp1, tmp2)
    1327           28 :          tmp(2) = MAX(tmp1, tmp2)
    1328              :       CASE (3)
    1329           32 :          tmp1 = tmp(1)
    1330           32 :          tmp2 = tmp(3)
    1331           32 :          tmp(1) = MIN(tmp1, tmp2)
    1332           32 :          tmp(3) = MAX(tmp1, tmp2)
    1333              :       CASE (4)
    1334           82 :          IF (.NOT. do_impr) THEN
    1335           10 :             tmp1 = tmp(1)
    1336           10 :             tmp2 = tmp(4)
    1337           10 :             tmp(1) = MIN(tmp1, tmp2)
    1338           10 :             IF (tmp(1) == tmp2) THEN
    1339            6 :                tmp3 = tmp(3)
    1340            6 :                tmp(3) = tmp(2)
    1341            6 :                tmp(2) = tmp3
    1342              :             END IF
    1343           10 :             tmp(4) = MAX(tmp1, tmp2)
    1344              :          ELSE
    1345           12 :             tt(1) = tmp(2)
    1346           12 :             tt(2) = tmp(3)
    1347           12 :             tt(3) = tmp(4)
    1348           12 :             CALL sort(tt, 3, ss)
    1349           12 :             tmp(2) = tt(1)
    1350           12 :             tmp(3) = tt(2)
    1351           12 :             tmp(4) = tt(3)
    1352              :          END IF
    1353              :       END SELECT
    1354              :       ! boundary to search
    1355         1788 :       DO istart = 1, ndim
    1356         1788 :          IF (Ilist1(istart) >= tmp(1)) EXIT
    1357              :       END DO
    1358              :       ! if nothing there stay within bounds
    1359           82 :       IF (istart <= ndim) THEN
    1360           76 :          IF (Ilist1(istart) > tmp(1) .AND. (istart /= 1)) istart = istart - 1
    1361              :       END IF
    1362          222 :       DO iend = istart, ndim
    1363          222 :          IF (Ilist1(iend) /= tmp(1)) EXIT
    1364              :       END DO
    1365           82 :       IF (iend == ndim + 1) iend = ndim
    1366              :       ! Final search in array
    1367              :       SELECT CASE (nsize)
    1368              :       CASE (2)
    1369           40 :          DO i = istart, iend
    1370           28 :             IF ((Ilist1(i) > tmp(1)) .OR. (Ilist2(i) > tmp(2))) EXIT
    1371           40 :             IF ((Ilist1(i) == tmp(1)) .AND. (Ilist2(i) == tmp(2))) THEN
    1372              :                found = .TRUE.
    1373              :                EXIT
    1374              :             END IF
    1375              :          END DO
    1376              :       CASE (3)
    1377           40 :          DO i = istart, iend
    1378           40 :             IF ((Ilist1(i) > tmp(1)) .OR. (Ilist2(i) > tmp(2)) .OR. (Ilist3(i) > tmp(3))) EXIT
    1379           40 :             IF ((Ilist1(i) == tmp(1)) .AND. (Ilist2(i) == tmp(2)) .AND. (Ilist3(i) == tmp(3))) THEN
    1380              :                found = .TRUE.
    1381              :                EXIT
    1382              :             END IF
    1383              :          END DO
    1384              :       CASE (4)
    1385          106 :          DO i = istart, iend
    1386           22 :             IF ((Ilist1(i) > tmp(1)) .OR. (Ilist2(i) > tmp(2)) .OR. (Ilist3(i) > tmp(3)) .OR. (Ilist4(i) > tmp(4))) EXIT
    1387              :             IF ((Ilist1(i) == tmp(1)) .AND. (Ilist2(i) == tmp(2)) &
    1388           24 :                 .AND. (Ilist3(i) == tmp(3)) .AND. (Ilist4(i) == tmp(4))) THEN
    1389              :                found = .TRUE.
    1390              :                EXIT
    1391              :             END IF
    1392              :          END DO
    1393              :       END SELECT
    1394          124 :       SELECT CASE (do_action)
    1395              :       CASE (do_add)
    1396           42 :          IF (found) THEN
    1397           16 :             do_it = -i
    1398              :             ! Nothing to modify. Element already present
    1399              :             ! in this case ABS(do_it) gives the exact location of the element
    1400              :             ! in the list
    1401              :          ELSE
    1402              :             ! Let's add the element in the right place of the list.. so that we can keep the
    1403              :             ! canonical order
    1404              :             ! in this case do_it gives the index of the list with indexes bigger than
    1405              :             ! the one we're searching for
    1406              :             ! At the end do_it gives the exact location of the element in the canonical list
    1407           26 :             do_it = i
    1408           26 :             new_size = ndim + 1
    1409           26 :             CALL reallocate(Ilist1, 1, new_size)
    1410           26 :             CALL reallocate(Ilist2, 1, new_size)
    1411          428 :             Ilist1(i + 1:new_size) = Ilist1(i:ndim)
    1412          428 :             Ilist2(i + 1:new_size) = Ilist2(i:ndim)
    1413           26 :             Ilist1(i) = tmp(1)
    1414           26 :             Ilist2(i) = tmp(2)
    1415            2 :             SELECT CASE (nsize)
    1416              :             CASE (3)
    1417            2 :                CALL reallocate(Ilist3, 1, new_size)
    1418           86 :                Ilist3(i + 1:new_size) = Ilist3(i:ndim)
    1419            2 :                Ilist3(i) = tmp(3)
    1420              :             CASE (4)
    1421            8 :                CALL reallocate(Ilist3, 1, new_size)
    1422            8 :                CALL reallocate(Ilist4, 1, new_size)
    1423          230 :                Ilist3(i + 1:new_size) = Ilist3(i:ndim)
    1424          230 :                Ilist4(i + 1:new_size) = Ilist4(i:ndim)
    1425            8 :                Ilist3(i) = tmp(3)
    1426           34 :                Ilist4(i) = tmp(4)
    1427              :             END SELECT
    1428              :          END IF
    1429              :       CASE (do_remove)
    1430           82 :          IF (found) THEN
    1431           34 :             do_it = i
    1432              :             ! Let's delete the element in position do_it
    1433           34 :             new_size = ndim - 1
    1434          506 :             Ilist1(i:new_size) = Ilist1(i + 1:ndim)
    1435          506 :             Ilist2(i:new_size) = Ilist2(i + 1:ndim)
    1436           34 :             CALL reallocate(Ilist1, 1, new_size)
    1437           34 :             CALL reallocate(Ilist2, 1, new_size)
    1438           16 :             SELECT CASE (nsize)
    1439              :             CASE (3)
    1440          260 :                Ilist3(i:new_size) = Ilist3(i + 1:ndim)
    1441           16 :                CALL reallocate(Ilist3, 1, new_size)
    1442              :             CASE (4)
    1443          146 :                Ilist3(i:new_size) = Ilist3(i + 1:ndim)
    1444          146 :                Ilist4(i:new_size) = Ilist4(i + 1:ndim)
    1445           14 :                CALL reallocate(Ilist3, 1, new_size)
    1446           48 :                CALL reallocate(Ilist4, 1, new_size)
    1447              :             END SELECT
    1448              :          ELSE
    1449            6 :             do_it = -i
    1450              :             ! Nothing to modify. Element not present in the list
    1451              :             ! in this case ABS(do_it) gives the exact location of the element
    1452              :             ! in the list
    1453              :          END IF
    1454              :       END SELECT
    1455           82 :    END SUBROUTINE check_element_list
    1456              : 
    1457              : ! **************************************************************************************************
    1458              : !> \brief Adds a bond to the generated bond list
    1459              : !> \param conn_info ...
    1460              : !> \param atm1 ...
    1461              : !> \param atm2 ...
    1462              : !> \param n_bonds ...
    1463              : !> \author Teodoro Laino 09.2006
    1464              : ! **************************************************************************************************
    1465       117086 :    SUBROUTINE add_bonds_list(conn_info, atm1, atm2, n_bonds)
    1466              :       TYPE(connectivity_info_type), POINTER              :: conn_info
    1467              :       INTEGER, INTENT(IN)                                :: atm1, atm2, n_bonds
    1468              : 
    1469              :       INTEGER                                            :: new_size, old_size
    1470              : 
    1471       117086 :       old_size = SIZE(conn_info%bond_a)
    1472       117086 :       IF (n_bonds > old_size) THEN
    1473         6032 :          new_size = INT(5 + 1.2*old_size)
    1474         6032 :          CALL reallocate(conn_info%bond_a, 1, new_size)
    1475         6032 :          CALL reallocate(conn_info%bond_b, 1, new_size)
    1476              :       END IF
    1477       117086 :       conn_info%bond_a(n_bonds) = atm1
    1478       117086 :       conn_info%bond_b(n_bonds) = atm2
    1479       117086 :    END SUBROUTINE add_bonds_list
    1480              : 
    1481              : ! **************************************************************************************************
    1482              : !> \brief Using a list of bonds, generate a list of bends
    1483              : !> \param topology ...
    1484              : !> \param subsys_section ...
    1485              : !> \author Teodoro Laino 09.2006
    1486              : ! **************************************************************************************************
    1487        21214 :    SUBROUTINE topology_generate_bend(topology, subsys_section)
    1488              :       TYPE(topology_parameters_type), INTENT(INOUT)      :: topology
    1489              :       TYPE(section_vals_type), POINTER                   :: subsys_section
    1490              : 
    1491              :       CHARACTER(len=*), PARAMETER :: routineN = 'topology_generate_bend'
    1492              : 
    1493              :       INTEGER                                            :: handle, handle2, i, iw, natom, nbond, &
    1494              :                                                             nsize, ntheta, output_unit
    1495        10607 :       TYPE(array1_list_type), DIMENSION(:), POINTER      :: bond_list
    1496              :       TYPE(connectivity_info_type), POINTER              :: conn_info
    1497              :       TYPE(cp_logger_type), POINTER                      :: logger
    1498              :       TYPE(section_vals_type), POINTER                   :: bend_section
    1499              : 
    1500        10607 :       NULLIFY (logger)
    1501        21214 :       logger => cp_get_default_logger()
    1502              :       iw = cp_print_key_unit_nr(logger, subsys_section, "PRINT%TOPOLOGY_INFO/GENERATE_INFO", &
    1503        10607 :                                 extension=".subsysLog")
    1504        10607 :       CALL timeset(routineN, handle)
    1505        10607 :       output_unit = cp_logger_get_default_io_unit(logger)
    1506        10607 :       conn_info => topology%conn_info
    1507        10607 :       nbond = 0
    1508        10607 :       ntheta = 0
    1509        10607 :       natom = topology%natoms
    1510              :       ! This call is for connectivity off
    1511        10607 :       IF (ASSOCIATED(conn_info%bond_a)) THEN
    1512         8881 :          nbond = SIZE(conn_info%bond_a)
    1513              :       ELSE
    1514         1726 :          CALL reallocate(conn_info%bond_a, 1, nbond)
    1515         1726 :          CALL reallocate(conn_info%bond_b, 1, nbond)
    1516              :       END IF
    1517        10607 :       IF (nbond /= 0) THEN
    1518         1924 :          nsize = INT(5 + 1.2*ntheta)
    1519         1924 :          CALL reallocate(conn_info%theta_a, 1, nsize)
    1520         1924 :          CALL reallocate(conn_info%theta_b, 1, nsize)
    1521         1924 :          CALL reallocate(conn_info%theta_c, 1, nsize)
    1522              :          ! Get list of bonds to pre-process theta
    1523       156946 :          ALLOCATE (bond_list(natom))
    1524       153098 :          DO I = 1, natom
    1525       153098 :             ALLOCATE (bond_list(I)%array1(0))
    1526              :          END DO
    1527         1924 :          CALL reorder_structure(bond_list, conn_info%bond_a, conn_info%bond_b, nbond)
    1528              :          ! All the dirty job is handled by this routine.. for bends it_levl is equal 3
    1529         1924 :          CALL timeset(routineN//"_1", handle2)
    1530              :          CALL match_iterative_path(Iarray1=bond_list, &
    1531              :                                    Iarray2=bond_list, &
    1532              :                                    max_levl=3, &
    1533              :                                    nvar=ntheta, &
    1534              :                                    Oarray1=conn_info%theta_a, &
    1535              :                                    Oarray2=conn_info%theta_b, &
    1536         1924 :                                    Oarray3=conn_info%theta_c)
    1537         1924 :          CALL timestop(handle2)
    1538       153098 :          DO I = 1, natom
    1539       153098 :             DEALLOCATE (bond_list(I)%array1)
    1540              :          END DO
    1541         1924 :          DEALLOCATE (bond_list)
    1542         1924 :          IF (output_unit > 0) THEN
    1543         1024 :             WRITE (output_unit, '(T2,"GENERATE|",1X,A,T71,I10)') " Preliminary Number of Bends generated:", &
    1544         2048 :                ntheta
    1545              :          END IF
    1546              :          ! External defined bends (useful for complex connectivity)
    1547         1924 :          bend_section => section_vals_get_subs_vals(subsys_section, "TOPOLOGY%GENERATE%ANGLE")
    1548              :          CALL connectivity_external_control(section=bend_section, &
    1549              :                                             Iarray1=conn_info%theta_a, &
    1550              :                                             Iarray2=conn_info%theta_b, &
    1551              :                                             Iarray3=conn_info%theta_c, &
    1552              :                                             nvar=ntheta, &
    1553              :                                             topology=topology, &
    1554         3848 :                                             output_unit=output_unit)
    1555              :       END IF
    1556              :       ! Resize arrays to their proper size..
    1557        10607 :       CALL reallocate(conn_info%theta_a, 1, ntheta)
    1558        10607 :       CALL reallocate(conn_info%theta_b, 1, ntheta)
    1559        10607 :       CALL reallocate(conn_info%theta_c, 1, ntheta)
    1560        10607 :       IF (output_unit > 0 .AND. ntheta > 0) THEN
    1561          970 :          WRITE (output_unit, '(T2,"GENERATE|",1X,A,T71,I10)') " Number of Bends generated:", &
    1562         1940 :             ntheta
    1563              :       END IF
    1564        10607 :       CALL timestop(handle)
    1565              :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
    1566        10607 :                                         "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
    1567        10607 :    END SUBROUTINE topology_generate_bend
    1568              : 
    1569              : !
    1570              : 
    1571              : ! **************************************************************************************************
    1572              : !> \brief Routine matching iteratively along a graph
    1573              : !> \param Iarray1 ...
    1574              : !> \param Iarray2 ...
    1575              : !> \param Iarray3 ...
    1576              : !> \param max_levl ...
    1577              : !> \param Oarray1 ...
    1578              : !> \param Oarray2 ...
    1579              : !> \param Oarray3 ...
    1580              : !> \param Oarray4 ...
    1581              : !> \param Ilist ...
    1582              : !> \param it_levl ...
    1583              : !> \param nvar ...
    1584              : !> \author Teodoro Laino 09.2006
    1585              : ! **************************************************************************************************
    1586       903320 :    RECURSIVE SUBROUTINE match_iterative_path(Iarray1, Iarray2, Iarray3, &
    1587       903320 :                                              max_levl, Oarray1, Oarray2, Oarray3, Oarray4, Ilist, it_levl, nvar)
    1588              :       TYPE(array1_list_type), DIMENSION(:), POINTER      :: Iarray1
    1589              :       TYPE(array1_list_type), DIMENSION(:), OPTIONAL, &
    1590              :          POINTER                                         :: Iarray2, Iarray3
    1591              :       INTEGER, INTENT(IN)                                :: max_levl
    1592              :       INTEGER, DIMENSION(:), POINTER                     :: Oarray1, Oarray2
    1593              :       INTEGER, DIMENSION(:), OPTIONAL, POINTER           :: Oarray3, Oarray4
    1594              :       INTEGER, DIMENSION(:), INTENT(INOUT), OPTIONAL     :: Ilist
    1595              :       INTEGER, INTENT(IN), OPTIONAL                      :: it_levl
    1596              :       INTEGER, INTENT(INOUT)                             :: nvar
    1597              : 
    1598              :       INTEGER                                            :: i, ind, j, my_levl, natom
    1599       903320 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: my_list
    1600              :       LOGICAL                                            :: check
    1601       903320 :       TYPE(array1_list_type), DIMENSION(:), POINTER      :: wrk
    1602              : 
    1603       903320 :       check = max_levl >= 2 .AND. max_levl <= 4
    1604            0 :       CPASSERT(check)
    1605       903320 :       IF (.NOT. PRESENT(Ilist)) THEN
    1606            0 :          SELECT CASE (max_levl)
    1607              :          CASE (2)
    1608            0 :             CPASSERT(.NOT. PRESENT(Iarray2))
    1609            0 :             CPASSERT(.NOT. PRESENT(Iarray3))
    1610            0 :             CPASSERT(.NOT. PRESENT(Oarray3))
    1611            0 :             CPASSERT(.NOT. PRESENT(Oarray4))
    1612              :          CASE (3)
    1613         1924 :             CPASSERT(PRESENT(Iarray2))
    1614         1924 :             CPASSERT(.NOT. PRESENT(Iarray3))
    1615         1924 :             CPASSERT(PRESENT(Oarray3))
    1616         1924 :             CPASSERT(.NOT. PRESENT(Oarray4))
    1617              :          CASE (4)
    1618         1924 :             CPASSERT(PRESENT(Iarray2))
    1619         1924 :             CPASSERT(PRESENT(Iarray3))
    1620         1924 :             CPASSERT(PRESENT(Oarray3))
    1621         5772 :             CPASSERT(PRESENT(Oarray4))
    1622              :          END SELECT
    1623              :       END IF
    1624       903320 :       natom = SIZE(Iarray1)
    1625       903320 :       IF (.NOT. PRESENT(Ilist)) THEN
    1626              :          ! Start a new loop.. Only the first time the routine is called
    1627        11544 :          ALLOCATE (my_list(max_levl))
    1628       306196 :          DO i = 1, natom
    1629       302348 :             my_levl = 1
    1630      1360566 :             my_list = -1
    1631       302348 :             my_list(my_levl) = i
    1632              :             CALL match_iterative_path(Iarray1=Iarray1, &
    1633              :                                       Iarray2=Iarray2, &
    1634              :                                       Iarray3=Iarray3, &
    1635              :                                       it_levl=my_levl + 1, &
    1636              :                                       max_levl=max_levl, &
    1637              :                                       Oarray1=Oarray1, &
    1638              :                                       Oarray2=Oarray2, &
    1639              :                                       Oarray3=Oarray3, &
    1640              :                                       Oarray4=Oarray4, &
    1641              :                                       nvar=nvar, &
    1642       306196 :                                       Ilist=my_list)
    1643              :          END DO
    1644         3848 :          DEALLOCATE (my_list)
    1645              :       ELSE
    1646      1201820 :          SELECT CASE (it_levl)
    1647              :          CASE (2)
    1648       302348 :             wrk => Iarray1
    1649              :          CASE (3)
    1650       429032 :             wrk => Iarray2
    1651              :          CASE (4)
    1652       899472 :             wrk => Iarray3
    1653              :          END SELECT
    1654       899472 :          i = Ilist(it_levl - 1)
    1655      2352140 :          DO j = 1, SIZE(Iarray1(i)%array1)
    1656      1452668 :             ind = wrk(i)%array1(j)
    1657      4658888 :             IF (ANY(Ilist == ind)) CYCLE
    1658      1754632 :             IF (it_levl < max_levl) THEN
    1659       597124 :                Ilist(it_levl) = ind
    1660              :                CALL match_iterative_path(Iarray1=Iarray1, &
    1661              :                                          Iarray2=Iarray2, &
    1662              :                                          Iarray3=Iarray3, &
    1663              :                                          it_levl=it_levl + 1, &
    1664              :                                          max_levl=max_levl, &
    1665              :                                          Oarray1=Oarray1, &
    1666              :                                          Oarray2=Oarray2, &
    1667              :                                          Oarray3=Oarray3, &
    1668              :                                          Oarray4=Oarray4, &
    1669              :                                          nvar=nvar, &
    1670       597124 :                                          Ilist=Ilist)
    1671       597124 :                Ilist(it_levl) = -1
    1672       258036 :             ELSEIF (it_levl == max_levl) THEN
    1673       258036 :                IF (Ilist(1) > ind) CYCLE
    1674       129018 :                Ilist(it_levl) = ind
    1675       129018 :                nvar = nvar + 1
    1676            0 :                SELECT CASE (it_levl)
    1677              :                CASE (2)
    1678            0 :                   IF (nvar > SIZE(Oarray1)) THEN
    1679            0 :                      CALL reallocate(Oarray1, 1, INT(5 + 1.2*nvar))
    1680            0 :                      CALL reallocate(Oarray2, 1, INT(5 + 1.2*nvar))
    1681              :                   END IF
    1682            0 :                   Oarray1(nvar) = Ilist(1)
    1683            0 :                   Oarray2(nvar) = Ilist(2)
    1684              :                CASE (3)
    1685        84046 :                   IF (nvar > SIZE(Oarray1)) THEN
    1686         3204 :                      CALL reallocate(Oarray1, 1, INT(5 + 1.2*nvar))
    1687         3204 :                      CALL reallocate(Oarray2, 1, INT(5 + 1.2*nvar))
    1688         3204 :                      CALL reallocate(Oarray3, 1, INT(5 + 1.2*nvar))
    1689              :                   END IF
    1690        84046 :                   Oarray1(nvar) = Ilist(1)
    1691        84046 :                   Oarray2(nvar) = Ilist(2)
    1692        84046 :                   Oarray3(nvar) = Ilist(3)
    1693              :                CASE (4)
    1694        44972 :                   IF (nvar > SIZE(Oarray1)) THEN
    1695         1436 :                      CALL reallocate(Oarray1, 1, INT(5 + 1.2*nvar))
    1696         1436 :                      CALL reallocate(Oarray2, 1, INT(5 + 1.2*nvar))
    1697         1436 :                      CALL reallocate(Oarray3, 1, INT(5 + 1.2*nvar))
    1698         1436 :                      CALL reallocate(Oarray4, 1, INT(5 + 1.2*nvar))
    1699              :                   END IF
    1700        44972 :                   Oarray1(nvar) = Ilist(1)
    1701        44972 :                   Oarray2(nvar) = Ilist(2)
    1702        44972 :                   Oarray3(nvar) = Ilist(3)
    1703        44972 :                   Oarray4(nvar) = Ilist(4)
    1704              :                CASE DEFAULT
    1705              :                   !should never reach this point
    1706       129018 :                   CPABORT("Only 2, 3, 4 are supported as the value of it_levl")
    1707              :                END SELECT
    1708       129018 :                Ilist(it_levl) = -1
    1709              :             ELSE
    1710              :                !should never reach this point
    1711            0 :                CPABORT("it_levl exceeds max_levl in match_iterative_path")
    1712              :             END IF
    1713              :          END DO
    1714              :       END IF
    1715      1806640 :    END SUBROUTINE match_iterative_path
    1716              : 
    1717              : !
    1718              : 
    1719              : ! **************************************************************************************************
    1720              : !> \brief The list of Urey-Bradley is equal to the list of bends
    1721              : !> \param topology ...
    1722              : !> \param subsys_section ...
    1723              : ! **************************************************************************************************
    1724        21214 :    SUBROUTINE topology_generate_ub(topology, subsys_section)
    1725              :       TYPE(topology_parameters_type), INTENT(INOUT)      :: topology
    1726              :       TYPE(section_vals_type), POINTER                   :: subsys_section
    1727              : 
    1728              :       CHARACTER(len=*), PARAMETER :: routineN = 'topology_generate_ub'
    1729              : 
    1730              :       INTEGER                                            :: handle, itheta, iw, ntheta, output_unit
    1731              :       TYPE(connectivity_info_type), POINTER              :: conn_info
    1732              :       TYPE(cp_logger_type), POINTER                      :: logger
    1733              : 
    1734        10607 :       NULLIFY (logger)
    1735        10607 :       logger => cp_get_default_logger()
    1736              :       iw = cp_print_key_unit_nr(logger, subsys_section, "PRINT%TOPOLOGY_INFO/GENERATE_INFO", &
    1737        10607 :                                 extension=".subsysLog")
    1738        10607 :       output_unit = cp_logger_get_default_io_unit(logger)
    1739        10607 :       CALL timeset(routineN, handle)
    1740        10607 :       conn_info => topology%conn_info
    1741        10607 :       ntheta = SIZE(conn_info%theta_a)
    1742        10607 :       CALL reallocate(conn_info%ub_a, 1, ntheta)
    1743        10607 :       CALL reallocate(conn_info%ub_b, 1, ntheta)
    1744        10607 :       CALL reallocate(conn_info%ub_c, 1, ntheta)
    1745              : 
    1746        94639 :       DO itheta = 1, ntheta
    1747        84032 :          conn_info%ub_a(itheta) = conn_info%theta_a(itheta)
    1748        84032 :          conn_info%ub_b(itheta) = conn_info%theta_b(itheta)
    1749        94639 :          conn_info%ub_c(itheta) = conn_info%theta_c(itheta)
    1750              :       END DO
    1751        10607 :       IF (output_unit > 0 .AND. ntheta > 0) THEN
    1752          970 :          WRITE (output_unit, '(T2,"GENERATE|",1X,A,T71,I10)') " Number of UB generated:", &
    1753         1940 :             ntheta
    1754              :       END IF
    1755        10607 :       CALL timestop(handle)
    1756              :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
    1757        10607 :                                         "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
    1758              : 
    1759        10607 :    END SUBROUTINE topology_generate_ub
    1760              : 
    1761              : ! **************************************************************************************************
    1762              : !> \brief Generate a list of torsions from bonds
    1763              : !> \param topology ...
    1764              : !> \param subsys_section ...
    1765              : !> \author Teodoro Laino 09.2006
    1766              : ! **************************************************************************************************
    1767        21214 :    SUBROUTINE topology_generate_dihe(topology, subsys_section)
    1768              :       TYPE(topology_parameters_type), INTENT(INOUT)      :: topology
    1769              :       TYPE(section_vals_type), POINTER                   :: subsys_section
    1770              : 
    1771              :       CHARACTER(len=*), PARAMETER :: routineN = 'topology_generate_dihe'
    1772              : 
    1773              :       INTEGER                                            :: handle, i, iw, natom, nbond, nphi, &
    1774              :                                                             nsize, output_unit
    1775        10607 :       TYPE(array1_list_type), DIMENSION(:), POINTER      :: bond_list
    1776              :       TYPE(connectivity_info_type), POINTER              :: conn_info
    1777              :       TYPE(cp_logger_type), POINTER                      :: logger
    1778              :       TYPE(section_vals_type), POINTER                   :: torsion_section
    1779              : 
    1780        10607 :       NULLIFY (logger)
    1781        21214 :       logger => cp_get_default_logger()
    1782              :       iw = cp_print_key_unit_nr(logger, subsys_section, "PRINT%TOPOLOGY_INFO/GENERATE_INFO", &
    1783        10607 :                                 extension=".subsysLog")
    1784        10607 :       output_unit = cp_logger_get_default_io_unit(logger)
    1785        10607 :       CALL timeset(routineN, handle)
    1786        10607 :       conn_info => topology%conn_info
    1787        10607 :       nphi = 0
    1788        10607 :       nbond = SIZE(conn_info%bond_a)
    1789        10607 :       IF (nbond /= 0) THEN
    1790         1924 :          nsize = INT(5 + 1.2*nphi)
    1791         1924 :          CALL reallocate(conn_info%phi_a, 1, nsize)
    1792         1924 :          CALL reallocate(conn_info%phi_b, 1, nsize)
    1793         1924 :          CALL reallocate(conn_info%phi_c, 1, nsize)
    1794         1924 :          CALL reallocate(conn_info%phi_d, 1, nsize)
    1795              :          ! Get list of bonds to pre-process phi
    1796         1924 :          natom = topology%natoms
    1797       156946 :          ALLOCATE (bond_list(natom))
    1798       153098 :          DO I = 1, natom
    1799       153098 :             ALLOCATE (bond_list(I)%array1(0))
    1800              :          END DO
    1801         1924 :          CALL reorder_structure(bond_list, conn_info%bond_a, conn_info%bond_b, nbond)
    1802              :          ! All the dirty job is handled by this routine.. for torsions it_levl is equal 4
    1803              :          CALL match_iterative_path(Iarray1=bond_list, &
    1804              :                                    Iarray2=bond_list, &
    1805              :                                    Iarray3=bond_list, &
    1806              :                                    max_levl=4, &
    1807              :                                    nvar=nphi, &
    1808              :                                    Oarray1=conn_info%phi_a, &
    1809              :                                    Oarray2=conn_info%phi_b, &
    1810              :                                    Oarray3=conn_info%phi_c, &
    1811         1924 :                                    Oarray4=conn_info%phi_d)
    1812       153098 :          DO I = 1, natom
    1813       153098 :             DEALLOCATE (bond_list(I)%array1)
    1814              :          END DO
    1815         1924 :          DEALLOCATE (bond_list)
    1816         1924 :          IF (output_unit > 0) THEN
    1817         1024 :             WRITE (output_unit, '(T2,"GENERATE|",1X,A,T71,I10)') " Preliminary Number of Torsions generated:", &
    1818         2048 :                nphi
    1819              :          END IF
    1820              :          ! External defined torsions (useful for complex connectivity)
    1821         1924 :          torsion_section => section_vals_get_subs_vals(subsys_section, "TOPOLOGY%GENERATE%TORSION")
    1822              :          CALL connectivity_external_control(section=torsion_section, &
    1823              :                                             Iarray1=conn_info%phi_a, &
    1824              :                                             Iarray2=conn_info%phi_b, &
    1825              :                                             Iarray3=conn_info%phi_c, &
    1826              :                                             Iarray4=conn_info%phi_d, &
    1827              :                                             nvar=nphi, &
    1828              :                                             topology=topology, &
    1829         1924 :                                             output_unit=output_unit)
    1830              :       END IF
    1831              :       ! Resize arrays to their proper size..
    1832        10607 :       CALL reallocate(conn_info%phi_a, 1, nphi)
    1833        10607 :       CALL reallocate(conn_info%phi_b, 1, nphi)
    1834        10607 :       CALL reallocate(conn_info%phi_c, 1, nphi)
    1835        10607 :       CALL reallocate(conn_info%phi_d, 1, nphi)
    1836        10607 :       IF (output_unit > 0 .AND. nphi > 0) THEN
    1837          222 :          WRITE (output_unit, '(T2,"GENERATE|",1X,A,T71,I10)') " Number of Torsions generated:", &
    1838          444 :             nphi
    1839              :       END IF
    1840        10607 :       CALL timestop(handle)
    1841              :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
    1842        10607 :                                         "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
    1843              : 
    1844        10607 :    END SUBROUTINE topology_generate_dihe
    1845              : 
    1846              : ! **************************************************************************************************
    1847              : !> \brief Using a list of bends, generate a list of impr
    1848              : !> \param topology ...
    1849              : !> \param subsys_section ...
    1850              : !> \author Teodoro Laino 09.2006
    1851              : ! **************************************************************************************************
    1852        21214 :    SUBROUTINE topology_generate_impr(topology, subsys_section)
    1853              :       TYPE(topology_parameters_type), INTENT(INOUT)      :: topology
    1854              :       TYPE(section_vals_type), POINTER                   :: subsys_section
    1855              : 
    1856              :       CHARACTER(len=*), PARAMETER :: routineN = 'topology_generate_impr'
    1857              : 
    1858              :       CHARACTER(LEN=2)                                   :: atm_symbol
    1859              :       INTEGER                                            :: handle, i, ind, iw, j, natom, nbond, &
    1860              :                                                             nimpr, nsize, output_unit
    1861              :       LOGICAL                                            :: accept_impr
    1862        10607 :       TYPE(array1_list_type), DIMENSION(:), POINTER      :: bond_list
    1863              :       TYPE(atom_info_type), POINTER                      :: atom_info
    1864              :       TYPE(connectivity_info_type), POINTER              :: conn_info
    1865              :       TYPE(cp_logger_type), POINTER                      :: logger
    1866              :       TYPE(section_vals_type), POINTER                   :: impr_section
    1867              : 
    1868        10607 :       NULLIFY (logger)
    1869        21214 :       logger => cp_get_default_logger()
    1870              :       iw = cp_print_key_unit_nr(logger, subsys_section, "PRINT%TOPOLOGY_INFO/GENERATE_INFO", &
    1871        10607 :                                 extension=".subsysLog")
    1872        10607 :       output_unit = cp_logger_get_default_io_unit(logger)
    1873        10607 :       CALL timeset(routineN, handle)
    1874        10607 :       atom_info => topology%atom_info
    1875        10607 :       conn_info => topology%conn_info
    1876        10607 :       natom = topology%natoms
    1877        10607 :       nimpr = 0
    1878        10607 :       nbond = SIZE(conn_info%bond_a)
    1879        10607 :       IF (nbond /= 0) THEN
    1880         1924 :          nsize = INT(5 + 1.2*nimpr)
    1881         1924 :          CALL reallocate(conn_info%impr_a, 1, nsize)
    1882         1924 :          CALL reallocate(conn_info%impr_b, 1, nsize)
    1883         1924 :          CALL reallocate(conn_info%impr_c, 1, nsize)
    1884         1924 :          CALL reallocate(conn_info%impr_d, 1, nsize)
    1885              :          ! Get list of bonds to pre-process phi
    1886       156946 :          ALLOCATE (bond_list(natom))
    1887       153098 :          DO I = 1, natom
    1888       153098 :             ALLOCATE (bond_list(I)%array1(0))
    1889              :          END DO
    1890         1924 :          CALL reorder_structure(bond_list, conn_info%bond_a, conn_info%bond_b, nbond)
    1891       153098 :          DO I = 1, natom
    1892              :             ! Count all atoms with three bonds
    1893       153098 :             IF (SIZE(bond_list(I)%array1) == 3) THEN
    1894              :                ! Problematic cases::
    1895              :                ! Nitrogen
    1896         3342 :                accept_impr = .TRUE.
    1897         3342 :                atm_symbol = TRIM(id2str(atom_info%id_element(i)))
    1898         3342 :                CALL uppercase(atm_symbol)
    1899         3342 :                IF (atm_symbol == "N ") THEN
    1900              :                   accept_impr = .FALSE.
    1901              :                   ! Impropers on Nitrogen only when there is another atom close to it
    1902              :                   ! with other 3 bonds
    1903         8712 :                   DO j = 1, 3
    1904         6534 :                      ind = bond_list(I)%array1(j)
    1905         8712 :                      IF (SIZE(bond_list(ind)%array1) == 3) accept_impr = .TRUE.
    1906              :                   END DO
    1907              :                END IF
    1908         2178 :                IF (.NOT. accept_impr) CYCLE
    1909         1914 :                nimpr = nimpr + 1
    1910         1914 :                IF (nimpr > SIZE(conn_info%impr_a)) THEN
    1911          136 :                   nsize = INT(5 + 1.2*nimpr)
    1912          136 :                   CALL reallocate(conn_info%impr_a, 1, nsize)
    1913          136 :                   CALL reallocate(conn_info%impr_b, 1, nsize)
    1914          136 :                   CALL reallocate(conn_info%impr_c, 1, nsize)
    1915          136 :                   CALL reallocate(conn_info%impr_d, 1, nsize)
    1916              :                END IF
    1917         1914 :                conn_info%impr_a(nimpr) = i
    1918         1914 :                conn_info%impr_b(nimpr) = bond_list(I)%array1(1)
    1919         1914 :                conn_info%impr_c(nimpr) = bond_list(I)%array1(2)
    1920         1914 :                conn_info%impr_d(nimpr) = bond_list(I)%array1(3)
    1921              :             END IF
    1922              :          END DO
    1923       153098 :          DO I = 1, natom
    1924       153098 :             DEALLOCATE (bond_list(I)%array1)
    1925              :          END DO
    1926         1924 :          DEALLOCATE (bond_list)
    1927              :          ! External defined impropers (useful for complex connectivity)
    1928         1924 :          impr_section => section_vals_get_subs_vals(subsys_section, "TOPOLOGY%GENERATE%IMPROPER")
    1929              :          CALL connectivity_external_control(section=impr_section, &
    1930              :                                             Iarray1=conn_info%impr_a, &
    1931              :                                             Iarray2=conn_info%impr_b, &
    1932              :                                             Iarray3=conn_info%impr_c, &
    1933              :                                             Iarray4=conn_info%impr_d, &
    1934              :                                             nvar=nimpr, &
    1935              :                                             topology=topology, &
    1936              :                                             output_unit=output_unit, &
    1937         1924 :                                             is_impr=.TRUE.)
    1938              :       END IF
    1939              :       ! Resize arrays to their proper size..
    1940        10607 :       CALL reallocate(conn_info%impr_a, 1, nimpr)
    1941        10607 :       CALL reallocate(conn_info%impr_b, 1, nimpr)
    1942        10607 :       CALL reallocate(conn_info%impr_c, 1, nimpr)
    1943        10607 :       CALL reallocate(conn_info%impr_d, 1, nimpr)
    1944        10607 :       IF (output_unit > 0 .AND. nimpr > 0) THEN
    1945           44 :          WRITE (output_unit, '(T2,"GENERATE|",1X,A,T71,I10)') " Number of Impropers generated:", &
    1946           88 :             nimpr
    1947              :       END IF
    1948        10607 :       CALL timestop(handle)
    1949              :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
    1950        10607 :                                         "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
    1951              : 
    1952        10607 :    END SUBROUTINE topology_generate_impr
    1953              : 
    1954              : ! **************************************************************************************************
    1955              : !> \brief Using a list of torsion, generate a list of onfo
    1956              : !> \param topology ...
    1957              : !> \param subsys_section ...
    1958              : ! **************************************************************************************************
    1959        10607 :    SUBROUTINE topology_generate_onfo(topology, subsys_section)
    1960              :       TYPE(topology_parameters_type), INTENT(INOUT)      :: topology
    1961              :       TYPE(section_vals_type), POINTER                   :: subsys_section
    1962              : 
    1963              :       CHARACTER(len=*), PARAMETER :: routineN = 'topology_generate_onfo'
    1964              : 
    1965              :       INTEGER                                            :: atom_a, atom_b, handle, i, ionfo, iw, &
    1966              :                                                             natom, nbond, nphi, ntheta, output_unit
    1967        10607 :       TYPE(array1_list_type), DIMENSION(:), POINTER      :: bond_list, phi_list, theta_list
    1968              :       TYPE(connectivity_info_type), POINTER              :: conn_info
    1969              :       TYPE(cp_logger_type), POINTER                      :: logger
    1970              : 
    1971        10607 :       NULLIFY (logger)
    1972        21214 :       logger => cp_get_default_logger()
    1973              :       iw = cp_print_key_unit_nr(logger, subsys_section, "PRINT%TOPOLOGY_INFO/GENERATE_INFO", &
    1974        10607 :                                 extension=".subsysLog")
    1975        10607 :       output_unit = cp_logger_get_default_io_unit(logger)
    1976        10607 :       CALL timeset(routineN, handle)
    1977              : 
    1978        10607 :       conn_info => topology%conn_info
    1979        10607 :       natom = topology%natoms
    1980              : 
    1981              :       ! Get list of bonds (sic). Get a list of bonded neighbors for every atom.
    1982       313289 :       ALLOCATE (bond_list(natom))
    1983       292075 :       DO i = 1, natom
    1984       292075 :          ALLOCATE (bond_list(i)%array1(0))
    1985              :       END DO
    1986        10607 :       nbond = SIZE(conn_info%bond_a)
    1987        10607 :       CALL reorder_structure(bond_list, conn_info%bond_a, conn_info%bond_b, nbond)
    1988              : 
    1989              :       ! Get a list of next nearest neighbors for every atom.
    1990       302682 :       ALLOCATE (theta_list(natom))
    1991       292075 :       DO i = 1, natom
    1992       292075 :          ALLOCATE (theta_list(i)%array1(0))
    1993              :       END DO
    1994        10607 :       ntheta = SIZE(conn_info%theta_a)
    1995        10607 :       CALL reorder_structure(theta_list, conn_info%theta_a, conn_info%theta_c, ntheta)
    1996              : 
    1997              :       ! Get a list of next next nearest neighbors for every atom.
    1998       302682 :       ALLOCATE (phi_list(natom))
    1999       292075 :       DO i = 1, natom
    2000       292075 :          ALLOCATE (phi_list(i)%array1(0))
    2001              :       END DO
    2002        10607 :       nphi = SIZE(conn_info%phi_a)
    2003        10607 :       CALL reorder_structure(phi_list, conn_info%phi_a, conn_info%phi_d, nphi)
    2004              : 
    2005              :       ! Allocate enough (possible too much)
    2006        10607 :       CALL reallocate(conn_info%onfo_a, 1, nphi)
    2007        10607 :       CALL reallocate(conn_info%onfo_b, 1, nphi)
    2008              : 
    2009        10607 :       ionfo = 0
    2010       292075 :       DO atom_a = 1, natom
    2011       382015 :          DO i = 1, SIZE(phi_list(atom_a)%array1)
    2012        89940 :             atom_b = phi_list(atom_a)%array1(i)
    2013              :             ! Avoid trivial duplicates.
    2014        89940 :             IF (atom_a > atom_b) CYCLE
    2015              :             ! Avoid onfo's in 4-rings.
    2016       157018 :             IF (ANY(atom_b == bond_list(atom_a)%array1)) CYCLE
    2017              :             ! Avoid onfo's in 5-rings.
    2018       206964 :             IF (ANY(atom_b == theta_list(atom_a)%array1)) CYCLE
    2019              :             ! Avoid onfo's in 6-rings.
    2020       214908 :             IF (ANY(atom_b == phi_list(atom_a)%array1(:i - 1))) CYCLE
    2021        44578 :             ionfo = ionfo + 1
    2022        44578 :             conn_info%onfo_a(ionfo) = atom_a
    2023       371408 :             conn_info%onfo_b(ionfo) = atom_b
    2024              :          END DO
    2025              :       END DO
    2026              : 
    2027              :       ! Reallocate such that just enough memory is used.
    2028        10607 :       CALL reallocate(conn_info%onfo_a, 1, ionfo)
    2029        10607 :       CALL reallocate(conn_info%onfo_b, 1, ionfo)
    2030              : 
    2031              :       ! Deallocate bond_list
    2032       292075 :       DO i = 1, natom
    2033       292075 :          DEALLOCATE (bond_list(i)%array1)
    2034              :       END DO
    2035        10607 :       DEALLOCATE (bond_list)
    2036              :       ! Deallocate theta_list
    2037       292075 :       DO i = 1, natom
    2038       292075 :          DEALLOCATE (theta_list(i)%array1)
    2039              :       END DO
    2040        10607 :       DEALLOCATE (theta_list)
    2041              :       ! Deallocate phi_list
    2042       292075 :       DO i = 1, natom
    2043       292075 :          DEALLOCATE (phi_list(i)%array1)
    2044              :       END DO
    2045        10607 :       DEALLOCATE (phi_list)
    2046              : 
    2047              :       ! Final output
    2048        10607 :       IF (output_unit > 0 .AND. ionfo > 0) THEN
    2049          222 :          WRITE (output_unit, '(T2,"GENERATE|",1X,A,T71,I10)') " Number of 1-4 interactions generated:", &
    2050          444 :             ionfo
    2051              :       END IF
    2052        10607 :       CALL timestop(handle)
    2053              :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
    2054        10607 :                                         "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
    2055              : 
    2056        21214 :    END SUBROUTINE topology_generate_onfo
    2057              : 
    2058              : END MODULE topology_generate_util
        

Generated by: LCOV version 2.0-1