LCOV - code coverage report
Current view: top level - src - topology_util.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 96.6 % 593 573
Test Date: 2025-12-04 06:27:48 Functions: 88.2 % 17 15

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Collection of subroutine needed for topology related things
      10              : !> \par History
      11              : !>     jgh (23-05-2004) Last atom of molecule information added
      12              : ! **************************************************************************************************
      13              : MODULE topology_util
      14              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      15              :                                               cp_logger_get_default_io_unit,&
      16              :                                               cp_logger_type,&
      17              :                                               cp_to_string
      18              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      19              :                                               cp_print_key_unit_nr
      20              :    USE graphcon,                        ONLY: graph_type,&
      21              :                                               hash_molecule,&
      22              :                                               reorder_graph,&
      23              :                                               vertex
      24              :    USE input_section_types,             ONLY: section_vals_get,&
      25              :                                               section_vals_get_subs_vals,&
      26              :                                               section_vals_type,&
      27              :                                               section_vals_val_get,&
      28              :                                               section_vals_val_set
      29              :    USE kinds,                           ONLY: default_string_length,&
      30              :                                               dp
      31              :    USE mm_mapping_library,              ONLY: amber_map,&
      32              :                                               charmm_map,&
      33              :                                               gromos_map
      34              :    USE periodic_table,                  ONLY: get_ptable_info
      35              :    USE qmmm_types_low,                  ONLY: qmmm_env_mm_type
      36              :    USE string_table,                    ONLY: id2str,&
      37              :                                               str2id
      38              :    USE string_utilities,                ONLY: uppercase
      39              :    USE topology_types,                  ONLY: atom_info_type,&
      40              :                                               connectivity_info_type,&
      41              :                                               topology_parameters_type
      42              :    USE util,                            ONLY: sort
      43              : #include "./base/base_uses.f90"
      44              : 
      45              :    IMPLICIT NONE
      46              : 
      47              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'topology_util'
      48              : 
      49              :    TYPE array1_list_type
      50              :       INTEGER, POINTER, DIMENSION(:) :: array1 => NULL()
      51              :    END TYPE array1_list_type
      52              : 
      53              :    TYPE array2_list_type
      54              :       INTEGER, POINTER, DIMENSION(:) :: array1 => NULL()
      55              :       INTEGER, POINTER, DIMENSION(:) :: array2 => NULL()
      56              :    END TYPE array2_list_type
      57              : 
      58              :    PRIVATE
      59              :    PUBLIC :: topology_set_atm_mass, &
      60              :              topology_reorder_atoms, &
      61              :              topology_molecules_check, &
      62              :              check_subsys_element, &
      63              :              reorder_structure, &
      64              :              find_molecule, &
      65              :              array1_list_type, &
      66              :              array2_list_type, &
      67              :              give_back_molecule, &
      68              :              reorder_list_array, &
      69              :              tag_molecule
      70              : 
      71              :    INTERFACE reorder_structure
      72              :       MODULE PROCEDURE reorder_structure1d, reorder_structure2d
      73              :    END INTERFACE
      74              : 
      75              : CONTAINS
      76              : 
      77              : ! **************************************************************************************************
      78              : !> \brief ...
      79              : !> \param topology ...
      80              : !> \param qmmm ...
      81              : !> \param qmmm_env_mm ...
      82              : !> \param subsys_section ...
      83              : !> \param force_env_section ...
      84              : !> \par History
      85              : !>      Teodoro Laino 09.2006 - Rewritten with a graph matching algorithm
      86              : ! **************************************************************************************************
      87          314 :    SUBROUTINE topology_reorder_atoms(topology, qmmm, qmmm_env_mm, subsys_section, force_env_section)
      88              :       TYPE(topology_parameters_type), INTENT(INOUT)      :: topology
      89              :       LOGICAL, INTENT(in), OPTIONAL                      :: qmmm
      90              :       TYPE(qmmm_env_mm_type), OPTIONAL, POINTER          :: qmmm_env_mm
      91              :       TYPE(section_vals_type), POINTER                   :: subsys_section, force_env_section
      92              : 
      93              :       CHARACTER(len=*), PARAMETER :: routineN = 'topology_reorder_atoms'
      94              : 
      95              :       CHARACTER(LEN=default_string_length)               :: mol_id
      96          314 :       CHARACTER(LEN=default_string_length), POINTER      :: molname(:), telement(:), &
      97          314 :                                                             tlabel_atmname(:), tlabel_molname(:), &
      98          314 :                                                             tlabel_resname(:)
      99              :       INTEGER :: handle, i, iatm, iindex, ikind, imol, imol_ref, iref, iund, iw, j, k, location, &
     100              :          max_mol_num, mm_index, n, n_rep, n_var, natom, natom_loc, nkind, nlinks, old_hash, &
     101              :          old_mol, output_unit, qm_index, unique_mol
     102          314 :       INTEGER, DIMENSION(:), POINTER                     :: mm_link_atoms, qm_atom_index
     103          314 :       INTEGER, POINTER :: atm_map1(:), atm_map2(:), atm_map3(:), map_atom_type(:), &
     104          314 :          map_mol_hash(:), mm_indexes_n(:), mm_indexes_v(:), mol_bnd(:, :), mol_hash(:), &
     105          314 :          mol_num(:), new_position(:), order(:), tmp_n(:), tmp_v(:), wrk(:)
     106              :       LOGICAL                                            :: explicit, matches, my_qmmm
     107          314 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: tr
     108          314 :       REAL(KIND=dp), POINTER                             :: tatm_charge(:), tatm_mass(:)
     109          314 :       TYPE(array1_list_type), ALLOCATABLE, DIMENSION(:)  :: atom_bond_list
     110              :       TYPE(atom_info_type), POINTER                      :: atom_info
     111              :       TYPE(connectivity_info_type), POINTER              :: conn_info
     112              :       TYPE(cp_logger_type), POINTER                      :: logger
     113          314 :       TYPE(graph_type), DIMENSION(:), POINTER            :: reference_set
     114              :       TYPE(section_vals_type), POINTER                   :: generate_section, isolated_section, &
     115              :                                                             qm_kinds, qmmm_link_section, &
     116              :                                                             qmmm_section
     117          314 :       TYPE(vertex), DIMENSION(:), POINTER                :: reference, unordered
     118              : 
     119          314 :       NULLIFY (logger, generate_section, isolated_section, tmp_v, tmp_n)
     120          628 :       logger => cp_get_default_logger()
     121              :       iw = cp_print_key_unit_nr(logger, subsys_section, "PRINT%TOPOLOGY_INFO/UTIL_INFO", &
     122          314 :                                 extension=".subsysLog")
     123          314 :       CALL timeset(routineN, handle)
     124          314 :       output_unit = cp_logger_get_default_io_unit(logger)
     125          314 :       IF (output_unit > 0) WRITE (output_unit, '(T2,"REORDER |  ")')
     126              : 
     127          314 :       my_qmmm = .FALSE.
     128          314 :       IF (PRESENT(qmmm) .AND. PRESENT(qmmm_env_mm)) my_qmmm = qmmm
     129              : 
     130          314 :       atom_info => topology%atom_info
     131          314 :       conn_info => topology%conn_info
     132          314 :       natom = topology%natoms
     133              : 
     134          314 :       NULLIFY (new_position, reference_set)
     135          314 :       NULLIFY (tlabel_atmname, telement, mol_num, tlabel_molname, tlabel_resname)
     136          314 :       NULLIFY (tr, tatm_charge, tatm_mass, atm_map1, atm_map2, atm_map3)
     137              :       ! This routine can be called only at a very high level where these structures are still
     138              :       ! not even taken into account...
     139          314 :       CPASSERT(.NOT. ASSOCIATED(atom_info%map_mol_num))
     140          314 :       CPASSERT(.NOT. ASSOCIATED(atom_info%map_mol_typ))
     141          314 :       CPASSERT(.NOT. ASSOCIATED(atom_info%map_mol_res))
     142              :       !ALLOCATE all the temporary arrays needed for this routine
     143          942 :       ALLOCATE (new_position(natom))
     144          628 :       ALLOCATE (mol_num(natom))
     145          942 :       ALLOCATE (molname(natom))
     146          628 :       ALLOCATE (tlabel_atmname(natom))
     147          628 :       ALLOCATE (tlabel_molname(natom))
     148          628 :       ALLOCATE (tlabel_resname(natom))
     149          942 :       ALLOCATE (tr(3, natom))
     150          942 :       ALLOCATE (tatm_charge(natom))
     151          628 :       ALLOCATE (tatm_mass(natom))
     152          628 :       ALLOCATE (telement(natom))
     153          628 :       ALLOCATE (atm_map1(natom))
     154          628 :       ALLOCATE (atm_map2(natom))
     155              : 
     156              :       ! The only information we have at this level is the connectivity of the system.
     157              :       ! 0. Build a list of mapping atom types
     158          628 :       ALLOCATE (map_atom_type(natom))
     159              :       ! 1. Build a list of bonds
     160         9500 :       ALLOCATE (atom_bond_list(natom))
     161         8872 :       DO I = 1, natom
     162         8558 :          map_atom_type(I) = atom_info%id_atmname(i)
     163         8872 :          ALLOCATE (atom_bond_list(I)%array1(0))
     164              :       END DO
     165          314 :       N = 0
     166          314 :       IF (ASSOCIATED(conn_info%bond_a)) N = SIZE(conn_info%bond_a)
     167          314 :       CALL reorder_structure(atom_bond_list, conn_info%bond_a, conn_info%bond_b, N)
     168          628 :       ALLOCATE (atom_info%map_mol_num(natom))
     169         8872 :       atom_info%map_mol_num = -1
     170          314 :       CALL find_molecule(atom_bond_list, atom_info%map_mol_num, atom_info%id_molname)
     171         8872 :       max_mol_num = MAXVAL(atom_info%map_mol_num)
     172              :       ! In atom_info%map_mol_num have already been mapped molecules
     173          942 :       ALLOCATE (mol_bnd(2, max_mol_num))
     174          942 :       ALLOCATE (mol_hash(max_mol_num))
     175          628 :       ALLOCATE (map_mol_hash(max_mol_num))
     176              :       ! 2. Sort the map_mol_num array.. atm_map1 contains now the mapped index
     177              :       !    of the reordered array
     178          314 :       CALL sort(atom_info%map_mol_num, natom, atm_map1)
     179          314 :       old_mol = 0
     180          314 :       iindex = 0
     181          314 :       imol = 0
     182         8872 :       DO i = 1, natom
     183         8558 :          IF (old_mol /= atom_info%map_mol_num(I)) THEN
     184         1420 :             old_mol = atom_info%map_mol_num(I)
     185         1420 :             iindex = 0
     186         1420 :             IF (imol > 0) THEN
     187         1106 :                mol_bnd(2, imol) = i - 1
     188              :             END IF
     189         1420 :             imol = imol + 1
     190         1420 :             mol_bnd(1, imol) = i
     191              :          END IF
     192         8558 :          iindex = iindex + 1
     193         8872 :          atm_map2(atm_map1(i)) = iindex
     194              :       END DO
     195          314 :       mol_bnd(2, imol) = natom
     196              :       ! Indexes of the two molecules to check
     197          314 :       iref = 1
     198          314 :       iund = max_mol_num/2 + 1
     199              :       ! Allocate reference and unordered
     200          314 :       NULLIFY (reference, unordered)
     201              :       ! This is the real matching of graphs
     202         1734 :       DO j = 1, max_mol_num
     203              :          CALL setup_graph(j, reference, map_atom_type, &
     204         1420 :                           atom_bond_list, mol_bnd, atm_map1, atm_map2)
     205              : 
     206         4260 :          ALLOCATE (order(SIZE(reference)))
     207         1420 :          CALL hash_molecule(reference, order, mol_hash(j))
     208              : 
     209         1420 :          DEALLOCATE (order)
     210         9978 :          DO I = 1, SIZE(reference)
     211         9978 :             DEALLOCATE (reference(I)%bonds)
     212              :          END DO
     213         1734 :          DEALLOCATE (reference)
     214              :       END DO
     215              :       ! Reorder molecules hashes
     216          314 :       CALL sort(mol_hash, max_mol_num, map_mol_hash)
     217              :       ! Now find unique molecules and reorder atoms too (if molecules match)
     218          314 :       old_hash = -1
     219          314 :       unique_mol = 0
     220          314 :       natom_loc = 0
     221          314 :       IF (output_unit > 0) THEN
     222              :          WRITE (output_unit, '(T2,"REORDER |  ",A)') &
     223          157 :             "Reordering Molecules. The Reordering of molecules will override all", &
     224          157 :             "information regarding molecule names and residue names.", &
     225          314 :             "New ones will be provided on the basis of the connectivity!"
     226              :       END IF
     227         1734 :       DO j = 1, max_mol_num
     228         1734 :          IF (mol_hash(j) /= old_hash) THEN
     229          326 :             unique_mol = unique_mol + 1
     230          326 :             old_hash = mol_hash(j)
     231              :             CALL setup_graph_set(reference_set, unique_mol, map_mol_hash(j), &
     232              :                                  map_atom_type, atom_bond_list, mol_bnd, atm_map1, atm_map2, &
     233          326 :                                  atm_map3)
     234              :             ! Reorder Last added reference
     235          326 :             mol_id = TRIM(ADJUSTL(cp_to_string(unique_mol)))
     236         5636 :             DO i = 1, SIZE(atm_map3)
     237         5310 :                natom_loc = natom_loc + 1
     238         5310 :                new_position(natom_loc) = atm_map3(i)
     239         5310 :                molname(natom_loc) = mol_id
     240         5636 :                mol_num(natom_loc) = unique_mol
     241              :             END DO
     242          326 :             DEALLOCATE (atm_map3)
     243              :          ELSE
     244              :             CALL setup_graph(map_mol_hash(j), unordered, map_atom_type, &
     245         1094 :                              atom_bond_list, mol_bnd, atm_map1, atm_map2, atm_map3)
     246         1150 :             DO imol_ref = 1, unique_mol
     247              :                !
     248         1150 :                reference => reference_set(imol_ref)%graph
     249         3450 :                ALLOCATE (order(SIZE(reference)))
     250         1150 :                CALL reorder_graph(reference, unordered, order, matches)
     251         1150 :                IF (matches) EXIT
     252         2300 :                DEALLOCATE (order)
     253              :             END DO
     254         1094 :             IF (matches) THEN
     255              :                ! Reorder according the correct index
     256         3282 :                ALLOCATE (wrk(SIZE(order)))
     257         1094 :                CALL sort(order, SIZE(order), wrk)
     258         4342 :                DO i = 1, SIZE(order)
     259         3248 :                   natom_loc = natom_loc + 1
     260         3248 :                   new_position(natom_loc) = atm_map3(wrk(i))
     261         3248 :                   molname(natom_loc) = mol_id
     262         4342 :                   mol_num(natom_loc) = unique_mol
     263              :                END DO
     264              :                !
     265         1094 :                DEALLOCATE (order)
     266         1094 :                DEALLOCATE (wrk)
     267              :             ELSE
     268            0 :                unique_mol = unique_mol + 1
     269              :                CALL setup_graph_set(reference_set, unique_mol, map_mol_hash(j), &
     270              :                                     map_atom_type, atom_bond_list, mol_bnd, atm_map1, atm_map2, &
     271            0 :                                     atm_map3)
     272              :                ! Reorder Last added reference
     273            0 :                mol_id = TRIM(ADJUSTL(cp_to_string(unique_mol)))
     274            0 :                DO i = 1, SIZE(atm_map3)
     275            0 :                   natom_loc = natom_loc + 1
     276            0 :                   new_position(natom_loc) = atm_map3(i)
     277            0 :                   molname(natom_loc) = mol_id
     278            0 :                   mol_num(natom_loc) = unique_mol
     279              :                END DO
     280            0 :                DEALLOCATE (atm_map3)
     281              :             END IF
     282         4342 :             DO I = 1, SIZE(unordered)
     283         4342 :                DEALLOCATE (unordered(I)%bonds)
     284              :             END DO
     285         1094 :             DEALLOCATE (unordered)
     286         1094 :             DEALLOCATE (atm_map3)
     287              :          END IF
     288              :       END DO
     289          314 :       IF (output_unit > 0) THEN
     290          157 :          WRITE (output_unit, '(T2,"REORDER |  ",A,I7,A)') "Number of unique molecules found:", unique_mol, "."
     291              :       END IF
     292          314 :       CPASSERT(natom_loc == natom)
     293          314 :       DEALLOCATE (map_atom_type)
     294          314 :       DEALLOCATE (atm_map1)
     295          314 :       DEALLOCATE (atm_map2)
     296          314 :       DEALLOCATE (mol_bnd)
     297          314 :       DEALLOCATE (mol_hash)
     298          314 :       DEALLOCATE (map_mol_hash)
     299              :       ! Deallocate working arrays
     300         8872 :       DO I = 1, natom
     301         8872 :          DEALLOCATE (atom_bond_list(I)%array1)
     302              :       END DO
     303          314 :       DEALLOCATE (atom_bond_list)
     304          314 :       DEALLOCATE (atom_info%map_mol_num)
     305              :       ! Deallocate reference_set
     306          640 :       DO i = 1, SIZE(reference_set)
     307         5636 :          DO j = 1, SIZE(reference_set(i)%graph)
     308         5636 :             DEALLOCATE (reference_set(i)%graph(j)%bonds)
     309              :          END DO
     310          640 :          DEALLOCATE (reference_set(i)%graph)
     311              :       END DO
     312          314 :       DEALLOCATE (reference_set)
     313              :       !Lets swap the atoms now
     314         8872 :       DO iatm = 1, natom
     315         8558 :          location = new_position(iatm)
     316         8558 :          tlabel_molname(iatm) = id2str(atom_info%id_molname(location))
     317         8558 :          tlabel_resname(iatm) = id2str(atom_info%id_resname(location))
     318         8558 :          tlabel_atmname(iatm) = id2str(atom_info%id_atmname(location))
     319         8558 :          telement(iatm) = id2str(atom_info%id_element(location))
     320         8558 :          tr(1, iatm) = atom_info%r(1, location)
     321         8558 :          tr(2, iatm) = atom_info%r(2, location)
     322         8558 :          tr(3, iatm) = atom_info%r(3, location)
     323         8558 :          tatm_charge(iatm) = atom_info%atm_charge(location)
     324         8872 :          tatm_mass(iatm) = atom_info%atm_mass(location)
     325              :       END DO
     326          314 :       IF (topology%create_molecules) THEN
     327         8858 :          DO iatm = 1, natom
     328         8546 :             tlabel_molname(iatm) = "MOL"//TRIM(molname(iatm))
     329         8858 :             tlabel_resname(iatm) = "R"//TRIM(molname(iatm))
     330              :          END DO
     331          312 :          topology%create_molecules = .FALSE.
     332              :       END IF
     333         8872 :       DO iatm = 1, natom
     334         8558 :          atom_info%id_molname(iatm) = str2id(tlabel_molname(iatm))
     335         8558 :          atom_info%id_resname(iatm) = str2id(tlabel_resname(iatm))
     336         8558 :          atom_info%id_atmname(iatm) = str2id(tlabel_atmname(iatm))
     337         8558 :          atom_info%id_element(iatm) = str2id(telement(iatm))
     338         8558 :          atom_info%resid(iatm) = mol_num(iatm)
     339         8558 :          atom_info%r(1, iatm) = tr(1, iatm)
     340         8558 :          atom_info%r(2, iatm) = tr(2, iatm)
     341         8558 :          atom_info%r(3, iatm) = tr(3, iatm)
     342         8558 :          atom_info%atm_charge(iatm) = tatm_charge(iatm)
     343         8872 :          atom_info%atm_mass(iatm) = tatm_mass(iatm)
     344              :       END DO
     345              : 
     346              :       ! Let's reorder all the list provided in the input..
     347          942 :       ALLOCATE (wrk(SIZE(new_position)))
     348          314 :       CALL sort(new_position, SIZE(new_position), wrk)
     349              : 
     350              :       ! NOTE: In the future the whole list of possible integers should be updated at this level..
     351              :       ! Let's update all the integer lists in the qmmm_env_mm section and in the input sections
     352              :       !       from where qmmm_env_qm will be read.
     353          314 :       IF (my_qmmm) THEN
     354              :          ! Update the qmmm_env_mm
     355            2 :          CPASSERT(SIZE(qmmm_env_mm%qm_atom_index) /= 0)
     356            8 :          CPASSERT(ALL(qmmm_env_mm%qm_atom_index /= 0))
     357            6 :          ALLOCATE (qm_atom_index(SIZE(qmmm_env_mm%qm_atom_index)))
     358            8 :          DO iatm = 1, SIZE(qmmm_env_mm%qm_atom_index)
     359            8 :             qm_atom_index(iatm) = wrk(qmmm_env_mm%qm_atom_index(iatm))
     360              :          END DO
     361           16 :          qmmm_env_mm%qm_atom_index = qm_atom_index
     362            8 :          CPASSERT(ALL(qmmm_env_mm%qm_atom_index /= 0))
     363            2 :          DEALLOCATE (qm_atom_index)
     364              :          ! Update the qmmm_section: MM_INDEX of the QM_KIND
     365            2 :          qmmm_section => section_vals_get_subs_vals(force_env_section, "QMMM")
     366            2 :          qm_kinds => section_vals_get_subs_vals(qmmm_section, "QM_KIND")
     367            2 :          CALL section_vals_get(qm_kinds, n_repetition=nkind)
     368            6 :          DO ikind = 1, nkind
     369            4 :             CALL section_vals_val_get(qm_kinds, "MM_INDEX", i_rep_section=ikind, n_rep_val=n_var)
     370           10 :             DO k = 1, n_var
     371              :                CALL section_vals_val_get(qm_kinds, "MM_INDEX", i_rep_section=ikind, i_rep_val=k, &
     372            4 :                                          i_vals=mm_indexes_v)
     373           12 :                ALLOCATE (mm_indexes_n(SIZE(mm_indexes_v)))
     374            8 :                DO j = 1, SIZE(mm_indexes_v)
     375            8 :                   mm_indexes_n(j) = wrk(mm_indexes_v(j))
     376              :                END DO
     377              :                CALL section_vals_val_set(qm_kinds, "MM_INDEX", i_rep_section=ikind, &
     378            8 :                                          i_vals_ptr=mm_indexes_n, i_rep_val=k)
     379              :             END DO
     380              :          END DO
     381              :          ! Handle the link atoms
     382            4 :          IF (qmmm_env_mm%qmmm_link) THEN
     383              :             ! Update the qmmm_env_mm
     384            2 :             CPASSERT(SIZE(qmmm_env_mm%mm_link_atoms) > 0)
     385            6 :             ALLOCATE (mm_link_atoms(SIZE(qmmm_env_mm%mm_link_atoms)))
     386            4 :             DO iatm = 1, SIZE(qmmm_env_mm%mm_link_atoms)
     387            4 :                mm_link_atoms(iatm) = wrk(qmmm_env_mm%mm_link_atoms(iatm))
     388              :             END DO
     389            8 :             qmmm_env_mm%mm_link_atoms = mm_link_atoms
     390            4 :             CPASSERT(ALL(qmmm_env_mm%mm_link_atoms /= 0))
     391            2 :             DEALLOCATE (mm_link_atoms)
     392              :             ! Update the qmmm_section: MM_INDEX,QM_INDEX of the LINK atom list
     393            2 :             qmmm_link_section => section_vals_get_subs_vals(qmmm_section, "LINK")
     394            2 :             CALL section_vals_get(qmmm_link_section, n_repetition=nlinks)
     395            2 :             CPASSERT(nlinks /= 0)
     396            6 :             DO ikind = 1, nlinks
     397            2 :                CALL section_vals_val_get(qmmm_link_section, "QM_INDEX", i_rep_section=ikind, i_val=qm_index)
     398            2 :                CALL section_vals_val_get(qmmm_link_section, "MM_INDEX", i_rep_section=ikind, i_val=mm_index)
     399            2 :                mm_index = wrk(mm_index)
     400            2 :                qm_index = wrk(qm_index)
     401            2 :                CALL section_vals_val_set(qmmm_link_section, "MM_INDEX", i_rep_section=ikind, i_val=mm_index)
     402            6 :                CALL section_vals_val_set(qmmm_link_section, "QM_INDEX", i_rep_section=ikind, i_val=qm_index)
     403              :             END DO
     404              :          END IF
     405              :       END IF
     406              :       !
     407              :       !LIST of ISOLATED atoms
     408              :       !
     409          314 :       generate_section => section_vals_get_subs_vals(subsys_section, "TOPOLOGY%GENERATE")
     410          314 :       isolated_section => section_vals_get_subs_vals(generate_section, "ISOLATED_ATOMS")
     411          314 :       CALL section_vals_get(isolated_section, explicit=explicit)
     412          314 :       IF (explicit) THEN
     413            4 :          CALL section_vals_val_get(isolated_section, "LIST", n_rep_val=n_rep)
     414           10 :          DO i = 1, n_rep
     415            6 :             CALL section_vals_val_get(isolated_section, "LIST", i_vals=tmp_v, i_rep_val=i)
     416           18 :             ALLOCATE (tmp_n(SIZE(tmp_v)))
     417           50 :             DO j = 1, SIZE(tmp_v)
     418           50 :                tmp_n(j) = wrk(tmp_v(j))
     419              :             END DO
     420           10 :             CALL section_vals_val_set(isolated_section, "LIST", i_vals_ptr=tmp_n, i_rep_val=i)
     421              :          END DO
     422              :       END IF
     423          314 :       DEALLOCATE (wrk)
     424              :       !DEALLOCATE all the temporary arrays needed for this routine
     425          314 :       DEALLOCATE (new_position)
     426          314 :       DEALLOCATE (tlabel_atmname)
     427          314 :       DEALLOCATE (tlabel_molname)
     428          314 :       DEALLOCATE (tlabel_resname)
     429          314 :       DEALLOCATE (telement)
     430          314 :       DEALLOCATE (tr)
     431          314 :       DEALLOCATE (tatm_charge)
     432          314 :       DEALLOCATE (tatm_mass)
     433          314 :       DEALLOCATE (molname)
     434          314 :       DEALLOCATE (mol_num)
     435              : 
     436              :       ! DEALLOCATE the bond structures in the connectivity
     437          314 :       DEALLOCATE (conn_info%bond_a)
     438          314 :       DEALLOCATE (conn_info%bond_b)
     439          314 :       IF (output_unit > 0) WRITE (output_unit, '(T2,"REORDER |  ")')
     440          314 :       CALL timestop(handle)
     441              :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
     442          314 :                                         "PRINT%TOPOLOGY_INFO/UTIL_INFO")
     443         1256 :    END SUBROUTINE topology_reorder_atoms
     444              : 
     445              : ! **************************************************************************************************
     446              : !> \brief Set up a SET of graph kind
     447              : !> \param graph_set ...
     448              : !> \param idim ...
     449              : !> \param ind ...
     450              : !> \param array2 ...
     451              : !> \param atom_bond_list ...
     452              : !> \param map_mol ...
     453              : !> \param atm_map1 ...
     454              : !> \param atm_map2 ...
     455              : !> \param atm_map3 ...
     456              : !> \author Teodoro Laino 10.2006
     457              : ! **************************************************************************************************
     458          326 :    SUBROUTINE setup_graph_set(graph_set, idim, ind, array2, atom_bond_list, map_mol, &
     459              :                               atm_map1, atm_map2, atm_map3)
     460              :       TYPE(graph_type), DIMENSION(:), POINTER            :: graph_set
     461              :       INTEGER, INTENT(IN)                                :: idim, ind
     462              :       INTEGER, DIMENSION(:), POINTER                     :: array2
     463              :       TYPE(array1_list_type), DIMENSION(:), INTENT(IN)   :: atom_bond_list
     464              :       INTEGER, DIMENSION(:, :), POINTER                  :: map_mol
     465              :       INTEGER, DIMENSION(:), POINTER                     :: atm_map1, atm_map2, atm_map3
     466              : 
     467              :       INTEGER                                            :: ldim
     468          326 :       TYPE(graph_type), DIMENSION(:), POINTER            :: tmp_graph_set
     469              : 
     470          326 :       ldim = 0
     471          326 :       NULLIFY (tmp_graph_set)
     472          326 :       IF (ASSOCIATED(graph_set)) THEN
     473           12 :          ldim = SIZE(graph_set)
     474           12 :          CPASSERT(ldim + 1 == idim)
     475              :          MARK_USED(idim)
     476              :          NULLIFY (tmp_graph_set)
     477           12 :          CALL allocate_graph_set(graph_set, tmp_graph_set)
     478              :       END IF
     479          326 :       CALL allocate_graph_set(tmp_graph_set, graph_set, ldim, ldim + 1)
     480              :       CALL setup_graph(ind, graph_set(ldim + 1)%graph, array2, &
     481          326 :                        atom_bond_list, map_mol, atm_map1, atm_map2, atm_map3)
     482              : 
     483          326 :    END SUBROUTINE setup_graph_set
     484              : 
     485              : ! **************************************************************************************************
     486              : !> \brief Allocate a new graph_set deallocating an old one..
     487              : !> \param graph_set_in ...
     488              : !> \param graph_set_out ...
     489              : !> \param ldim_in ...
     490              : !> \param ldim_out ...
     491              : !> \author Teodoro Laino 10.2006
     492              : ! **************************************************************************************************
     493          338 :    SUBROUTINE allocate_graph_set(graph_set_in, graph_set_out, ldim_in, ldim_out)
     494              :       TYPE(graph_type), DIMENSION(:), POINTER            :: graph_set_in, graph_set_out
     495              :       INTEGER, INTENT(IN), OPTIONAL                      :: ldim_in, ldim_out
     496              : 
     497              :       INTEGER                                            :: b_dim, i, j, mydim_in, mydim_out, v_dim
     498              : 
     499          338 :       CPASSERT(.NOT. ASSOCIATED(graph_set_out))
     500          338 :       mydim_in = 0
     501          338 :       mydim_out = 0
     502          338 :       IF (ASSOCIATED(graph_set_in)) THEN
     503           24 :          mydim_in = SIZE(graph_set_in)
     504           24 :          mydim_out = SIZE(graph_set_in)
     505              :       END IF
     506          338 :       IF (PRESENT(ldim_in)) mydim_in = ldim_in
     507          338 :       IF (PRESENT(ldim_out)) mydim_out = ldim_out
     508         1372 :       ALLOCATE (graph_set_out(mydim_out))
     509          696 :       DO i = 1, mydim_out
     510          696 :          NULLIFY (graph_set_out(i)%graph)
     511              :       END DO
     512              :       ! Copy graph structure into the temporary array
     513          370 :       DO i = 1, mydim_in
     514           32 :          v_dim = SIZE(graph_set_in(i)%graph)
     515          332 :          ALLOCATE (graph_set_out(i)%graph(v_dim))
     516          268 :          DO j = 1, v_dim
     517          236 :             graph_set_out(i)%graph(j)%kind = graph_set_in(i)%graph(j)%kind
     518          236 :             b_dim = SIZE(graph_set_in(i)%graph(j)%bonds)
     519          700 :             ALLOCATE (graph_set_out(i)%graph(j)%bonds(b_dim))
     520         1304 :             graph_set_out(i)%graph(j)%bonds = graph_set_in(i)%graph(j)%bonds
     521          268 :             DEALLOCATE (graph_set_in(i)%graph(j)%bonds)
     522              :          END DO
     523          370 :          DEALLOCATE (graph_set_in(i)%graph)
     524              :       END DO
     525          338 :       IF (ASSOCIATED(graph_set_in)) THEN
     526           24 :          DEALLOCATE (graph_set_in)
     527              :       END IF
     528              : 
     529          338 :    END SUBROUTINE allocate_graph_set
     530              : 
     531              : ! **************************************************************************************************
     532              : !> \brief Set up a graph kind
     533              : !> \param ind ...
     534              : !> \param graph ...
     535              : !> \param array2 ...
     536              : !> \param atom_bond_list ...
     537              : !> \param map_mol ...
     538              : !> \param atm_map1 ...
     539              : !> \param atm_map2 ...
     540              : !> \param atm_map3 ...
     541              : !> \author Teodoro Laino 09.2006
     542              : ! **************************************************************************************************
     543         2840 :    SUBROUTINE setup_graph(ind, graph, array2, atom_bond_list, map_mol, &
     544              :                           atm_map1, atm_map2, atm_map3)
     545              :       INTEGER, INTENT(IN)                                :: ind
     546              :       TYPE(vertex), DIMENSION(:), POINTER                :: graph
     547              :       INTEGER, DIMENSION(:), POINTER                     :: array2
     548              :       TYPE(array1_list_type), DIMENSION(:), INTENT(IN)   :: atom_bond_list
     549              :       INTEGER, DIMENSION(:, :), POINTER                  :: map_mol
     550              :       INTEGER, DIMENSION(:), POINTER                     :: atm_map1, atm_map2
     551              :       INTEGER, DIMENSION(:), OPTIONAL, POINTER           :: atm_map3
     552              : 
     553              :       INTEGER                                            :: i, idim, ifirst, ilast, j, nbonds, &
     554              :                                                             nelement
     555              : 
     556         2840 :       IF (PRESENT(atm_map3)) THEN
     557         1420 :          CPASSERT(.NOT. ASSOCIATED(atm_map3))
     558              :       END IF
     559         2840 :       CPASSERT(.NOT. ASSOCIATED(graph))
     560              :       ! Setup reference graph
     561         2840 :       idim = 0
     562         2840 :       ifirst = map_mol(1, ind)
     563         2840 :       ilast = map_mol(2, ind)
     564         2840 :       nelement = ilast - ifirst + 1
     565        25636 :       ALLOCATE (graph(nelement))
     566         2840 :       IF (PRESENT(atm_map3)) THEN
     567         4260 :          ALLOCATE (atm_map3(nelement))
     568              :       END IF
     569        19956 :       DO i = ifirst, ilast
     570        17116 :          idim = idim + 1
     571        17116 :          graph(idim)%kind = array2(atm_map1(i))
     572        17116 :          nbonds = SIZE(atom_bond_list(atm_map1(i))%array1)
     573        51260 :          ALLOCATE (graph(idim)%bonds(nbonds))
     574        49220 :          DO j = 1, nbonds
     575        49220 :             graph(idim)%bonds(j) = atm_map2(atom_bond_list(atm_map1(i))%array1(j))
     576              :          END DO
     577        19956 :          IF (PRESENT(atm_map3)) THEN
     578         8558 :             atm_map3(idim) = atm_map1(i)
     579              :          END IF
     580              :       END DO
     581              : 
     582         2840 :    END SUBROUTINE setup_graph
     583              : 
     584              : ! **************************************************************************************************
     585              : !> \brief Order arrays of lists
     586              : !> \param Ilist1 ...
     587              : !> \param Ilist2 ...
     588              : !> \param Ilist3 ...
     589              : !> \param Ilist4 ...
     590              : !> \param nsize ...
     591              : !> \param ndim ...
     592              : !> \author Teodoro Laino 09.2006
     593              : ! **************************************************************************************************
     594       261436 :    RECURSIVE SUBROUTINE reorder_list_array(Ilist1, Ilist2, Ilist3, Ilist4, nsize, ndim)
     595              :       INTEGER, DIMENSION(:), POINTER                     :: Ilist1
     596              :       INTEGER, DIMENSION(:), OPTIONAL, POINTER           :: Ilist2, Ilist3, Ilist4
     597              :       INTEGER, INTENT(IN)                                :: nsize, ndim
     598              : 
     599              :       INTEGER                                            :: i, iend, istart, ldim
     600       261436 :       INTEGER, DIMENSION(:), POINTER                     :: tmp, wrk
     601              : 
     602            0 :       CPASSERT(nsize > 0)
     603       759414 :       ALLOCATE (wrk(Ndim))
     604       261436 :       CALL sort(Ilist1, Ndim, wrk)
     605       261436 :       IF (nsize /= 1) THEN
     606       212277 :          ALLOCATE (tmp(Ndim))
     607      1054990 :          tmp = Ilist2(1:Ndim)
     608       527495 :          DO i = 1, Ndim
     609       527495 :             Ilist2(i) = tmp(wrk(i))
     610              :          END DO
     611        19724 :          SELECT CASE (nsize)
     612              :          CASE (3)
     613       293172 :             tmp = Ilist3(1:Ndim)
     614       146586 :             DO i = 1, Ndim
     615       146586 :                Ilist3(i) = tmp(wrk(i))
     616              :             END DO
     617              :          CASE (4)
     618        96364 :             tmp = Ilist3(1:Ndim)
     619        48182 :             DO i = 1, Ndim
     620        48182 :                Ilist3(i) = tmp(wrk(i))
     621              :             END DO
     622        96364 :             tmp = Ilist4(1:Ndim)
     623       162149 :             DO i = 1, Ndim
     624        48182 :                Ilist4(i) = tmp(wrk(i))
     625              :             END DO
     626              :          END SELECT
     627       113967 :          DEALLOCATE (tmp)
     628       113967 :          istart = 1
     629       527495 :          DO i = 1, Ndim
     630       527495 :             IF (Ilist1(i) /= Ilist1(istart)) THEN
     631       133780 :                iend = i - 1
     632       133780 :                ldim = iend - istart + 1
     633              :                CALL reorder_list_array_low(Ilist2, Ilist3, Ilist4, nsize, &
     634       133780 :                                            ldim, istart, iend)
     635       133780 :                istart = i
     636              :             END IF
     637              :          END DO
     638              :          ! Last term to sort
     639       113967 :          iend = Ndim
     640       113967 :          ldim = iend - istart + 1
     641              :          CALL reorder_list_array_low(Ilist2, Ilist3, Ilist4, nsize, &
     642       113967 :                                      ldim, istart, iend)
     643              :       END IF
     644       261436 :       DEALLOCATE (wrk)
     645       261436 :    END SUBROUTINE reorder_list_array
     646              : 
     647              : ! **************************************************************************************************
     648              : !> \brief Low level routine for ordering arrays of lists
     649              : !> \param Ilist2 ...
     650              : !> \param Ilist3 ...
     651              : !> \param Ilist4 ...
     652              : !> \param nsize ...
     653              : !> \param ldim ...
     654              : !> \param istart ...
     655              : !> \param iend ...
     656              : !> \author Teodoro Laino 09.2006
     657              : ! **************************************************************************************************
     658       247747 :    RECURSIVE SUBROUTINE reorder_list_array_low(Ilist2, Ilist3, Ilist4, nsize, &
     659              :                                                ldim, istart, iend)
     660              :       INTEGER, DIMENSION(:), OPTIONAL, POINTER           :: Ilist2, Ilist3, Ilist4
     661              :       INTEGER, INTENT(IN)                                :: nsize, ldim, istart, iend
     662              : 
     663       247747 :       INTEGER, DIMENSION(:), POINTER                     :: tmp_2, tmp_3, tmp_4
     664              : 
     665       395216 :       SELECT CASE (nsize)
     666              :       CASE (2)
     667       433170 :          ALLOCATE (tmp_2(ldim))
     668       779298 :          tmp_2(:) = Ilist2(istart:iend)
     669       147469 :          CALL reorder_list_array(tmp_2, nsize=nsize - 1, ndim=ldim)
     670       779298 :          Ilist2(istart:iend) = tmp_2(:)
     671       147469 :          DEALLOCATE (tmp_2)
     672              :       CASE (3)
     673       243952 :          ALLOCATE (tmp_2(ldim))
     674       240698 :          ALLOCATE (tmp_3(ldim))
     675       418528 :          tmp_2(:) = Ilist2(istart:iend)
     676       497676 :          tmp_3(:) = Ilist3(istart:iend)
     677        82402 :          CALL reorder_list_array(tmp_2, tmp_3, nsize=nsize - 1, ndim=ldim)
     678       418528 :          Ilist2(istart:iend) = tmp_2(:)
     679       418528 :          Ilist3(istart:iend) = tmp_3(:)
     680        82402 :          DEALLOCATE (tmp_2)
     681        82402 :          DEALLOCATE (tmp_3)
     682              :       CASE (4)
     683        50462 :          ALLOCATE (tmp_2(ldim))
     684        47296 :          ALLOCATE (tmp_3(ldim))
     685        47296 :          ALLOCATE (tmp_4(ldim))
     686       124724 :          tmp_2(:) = Ilist2(istart:iend)
     687       139434 :          tmp_3(:) = Ilist3(istart:iend)
     688       139434 :          tmp_4(:) = Ilist4(istart:iend)
     689        17876 :          CALL reorder_list_array(tmp_2, tmp_3, tmp_4, nsize=nsize - 1, ndim=ldim)
     690       124724 :          Ilist2(istart:iend) = tmp_2(:)
     691       124724 :          Ilist3(istart:iend) = tmp_3(:)
     692       124724 :          Ilist4(istart:iend) = tmp_4(:)
     693        17876 :          DEALLOCATE (tmp_2)
     694        17876 :          DEALLOCATE (tmp_3)
     695        17876 :          DEALLOCATE (tmp_4)
     696              :       END SELECT
     697              : 
     698       247747 :    END SUBROUTINE reorder_list_array_low
     699              : 
     700              : ! **************************************************************************************************
     701              : !> \brief ...
     702              : !> \param icheck ...
     703              : !> \param bond_list ...
     704              : !> \param i ...
     705              : !> \param mol_natom ...
     706              : !> \param mol_map ...
     707              : !> \param my_mol ...
     708              : !> \author Teodoro Laino 09.2006
     709              : ! **************************************************************************************************
     710       209112 :    RECURSIVE SUBROUTINE give_back_molecule(icheck, bond_list, i, mol_natom, mol_map, my_mol)
     711              :       LOGICAL, DIMENSION(:), POINTER                     :: icheck
     712              :       TYPE(array1_list_type), DIMENSION(:), POINTER      :: bond_list
     713              :       INTEGER, INTENT(IN)                                :: i
     714              :       INTEGER, INTENT(INOUT)                             :: mol_natom
     715              :       INTEGER, DIMENSION(:), POINTER                     :: mol_map
     716              :       INTEGER, INTENT(IN)                                :: my_mol
     717              : 
     718              :       INTEGER                                            :: j, k
     719              : 
     720       209112 :       IF (mol_map(i) == my_mol) THEN
     721       209104 :          icheck(i) = .TRUE.
     722       423728 :          DO j = 1, SIZE(bond_list(i)%array1)
     723       214624 :             k = bond_list(i)%array1(j)
     724       214624 :             IF (icheck(k)) CYCLE
     725       106312 :             mol_natom = mol_natom + 1
     726       423728 :             CALL give_back_molecule(icheck, bond_list, k, mol_natom, mol_map, my_mol)
     727              :          END DO
     728              :       ELSE
     729              :          ! Do nothing means only that bonds were found between molecules
     730              :          ! as we defined them.. This could easily be a bond detected but not
     731              :          ! physically present.. so just skip this part and go on..
     732              :       END IF
     733       209112 :    END SUBROUTINE give_back_molecule
     734              : 
     735              : ! **************************************************************************************************
     736              : !> \brief gives back a mapping of molecules.. icheck needs to be initialized with -1
     737              : !> \param icheck ...
     738              : !> \param bond_list ...
     739              : !> \param i ...
     740              : !> \param my_mol ...
     741              : !> \author Teodoro Laino 04.2007 - Zurich University
     742              : ! **************************************************************************************************
     743         6706 :    RECURSIVE SUBROUTINE tag_molecule(icheck, bond_list, i, my_mol)
     744              :       INTEGER, DIMENSION(:), POINTER                     :: icheck
     745              :       TYPE(array1_list_type), DIMENSION(:), POINTER      :: bond_list
     746              :       INTEGER, INTENT(IN)                                :: i, my_mol
     747              : 
     748              :       INTEGER                                            :: j, k
     749              : 
     750         6706 :       icheck(i) = my_mol
     751        17898 :       DO j = 1, SIZE(bond_list(i)%array1)
     752        11192 :          k = bond_list(i)%array1(j)
     753        11192 :          IF (k <= i) CYCLE
     754        17898 :          CALL tag_molecule(icheck, bond_list, k, my_mol)
     755              :       END DO
     756              : 
     757         6706 :    END SUBROUTINE tag_molecule
     758              : 
     759              : ! **************************************************************************************************
     760              : !> \brief Given two lists of corresponding element a complex type is built in
     761              : !>      which each element of the type has a list of mapping elements
     762              : !> \param work ...
     763              : !> \param list1 ...
     764              : !> \param list2 ...
     765              : !> \param N ...
     766              : !> \author Teodoro Laino 08.2006
     767              : ! **************************************************************************************************
     768        71993 :    SUBROUTINE reorder_structure1d(work, list1, list2, N)
     769              :       TYPE(array1_list_type), DIMENSION(:), &
     770              :          INTENT(INOUT)                                   :: work
     771              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: list1, list2
     772              :       INTEGER, INTENT(IN)                                :: N
     773              : 
     774              :       INTEGER                                            :: I, index1, index2, Nsize
     775        71993 :       INTEGER, DIMENSION(:), POINTER                     :: wrk_tmp
     776              : 
     777      3374455 :       DO I = 1, N
     778      3302462 :          index1 = list1(I)
     779      3302462 :          index2 = list2(I)
     780              : 
     781      3302462 :          wrk_tmp => work(index1)%array1
     782      3302462 :          Nsize = SIZE(wrk_tmp)
     783      9907386 :          ALLOCATE (work(index1)%array1(Nsize + 1))
     784      6455025 :          work(index1)%array1(1:Nsize) = wrk_tmp
     785      3302462 :          work(index1)%array1(Nsize + 1) = index2
     786      3302462 :          DEALLOCATE (wrk_tmp)
     787              : 
     788      3302462 :          wrk_tmp => work(index2)%array1
     789      3302462 :          Nsize = SIZE(wrk_tmp)
     790      9907386 :          ALLOCATE (work(index2)%array1(Nsize + 1))
     791      4519961 :          work(index2)%array1(1:Nsize) = wrk_tmp
     792      3302462 :          work(index2)%array1(Nsize + 1) = index1
     793      3374455 :          DEALLOCATE (wrk_tmp)
     794              :       END DO
     795              : 
     796        71993 :    END SUBROUTINE reorder_structure1d
     797              : 
     798              : ! **************************************************************************************************
     799              : !> \brief Given two lists of corresponding element a complex type is built in
     800              : !>      which each element of the type has a list of mapping elements
     801              : !> \param work ...
     802              : !> \param list1 ...
     803              : !> \param list2 ...
     804              : !> \param list3 ...
     805              : !> \param N ...
     806              : !> \author Teodoro Laino 09.2006
     807              : ! **************************************************************************************************
     808         8143 :    SUBROUTINE reorder_structure2d(work, list1, list2, list3, N)
     809              :       TYPE(array2_list_type), DIMENSION(:), &
     810              :          INTENT(INOUT)                                   :: work
     811              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: list1, list2, list3
     812              :       INTEGER, INTENT(IN)                                :: N
     813              : 
     814              :       INTEGER                                            :: I, index1, index2, index3, Nsize
     815         8143 :       INTEGER, DIMENSION(:), POINTER                     :: wrk_tmp
     816              : 
     817      1147844 :       DO I = 1, N
     818      1139701 :          index1 = list1(I)
     819      1139701 :          index2 = list2(I)
     820      1139701 :          index3 = list3(I)
     821              : 
     822      1139701 :          wrk_tmp => work(index1)%array1
     823      1139701 :          Nsize = SIZE(wrk_tmp)
     824      3419103 :          ALLOCATE (work(index1)%array1(Nsize + 1))
     825     23874175 :          work(index1)%array1(1:Nsize) = wrk_tmp
     826      1139701 :          work(index1)%array1(Nsize + 1) = index2
     827      1139701 :          DEALLOCATE (wrk_tmp)
     828              : 
     829      1139701 :          wrk_tmp => work(index2)%array1
     830      1139701 :          Nsize = SIZE(wrk_tmp)
     831      3419103 :          ALLOCATE (work(index2)%array1(Nsize + 1))
     832     15755001 :          work(index2)%array1(1:Nsize) = wrk_tmp
     833      1139701 :          work(index2)%array1(Nsize + 1) = index1
     834      1139701 :          DEALLOCATE (wrk_tmp)
     835              : 
     836      1139701 :          wrk_tmp => work(index1)%array2
     837      1139701 :          Nsize = SIZE(wrk_tmp)
     838      3419103 :          ALLOCATE (work(index1)%array2(Nsize + 1))
     839     23874175 :          work(index1)%array2(1:Nsize) = wrk_tmp
     840      1139701 :          work(index1)%array2(Nsize + 1) = index3
     841      1139701 :          DEALLOCATE (wrk_tmp)
     842              : 
     843      1139701 :          wrk_tmp => work(index2)%array2
     844      1139701 :          Nsize = SIZE(wrk_tmp)
     845      3419103 :          ALLOCATE (work(index2)%array2(Nsize + 1))
     846     15755001 :          work(index2)%array2(1:Nsize) = wrk_tmp
     847      1139701 :          work(index2)%array2(Nsize + 1) = -index3
     848      1147844 :          DEALLOCATE (wrk_tmp)
     849              :       END DO
     850              : 
     851         8143 :    END SUBROUTINE reorder_structure2d
     852              : 
     853              : ! **************************************************************************************************
     854              : !> \brief each atom will be assigned a molecule number based on bonded fragments
     855              : !>      The array mol_info should be initialized with -1 before calling the
     856              : !>      find_molecule routine
     857              : !> \param atom_bond_list ...
     858              : !> \param mol_info ...
     859              : !> \param mol_name ...
     860              : !> \author Joost 05.2006
     861              : ! **************************************************************************************************
     862        10588 :    SUBROUTINE find_molecule(atom_bond_list, mol_info, mol_name)
     863              :       TYPE(array1_list_type), DIMENSION(:), INTENT(IN)   :: atom_bond_list
     864              :       INTEGER, DIMENSION(:), POINTER                     :: mol_info, mol_name
     865              : 
     866              :       INTEGER                                            :: I, my_mol_name, N, nmol
     867              : 
     868        10588 :       N = SIZE(atom_bond_list)
     869        10588 :       nmol = 0
     870       773715 :       DO I = 1, N
     871       773715 :          IF (mol_info(I) == -1) THEN
     872       330784 :             nmol = nmol + 1
     873       330784 :             my_mol_name = mol_name(I)
     874              :             CALL spread_mol(atom_bond_list, mol_info, i, nmol, my_mol_name, &
     875       330784 :                             mol_name)
     876              :          END IF
     877              :       END DO
     878        10588 :    END SUBROUTINE find_molecule
     879              : 
     880              : ! **************************************************************************************************
     881              : !> \brief spreads the molnumber over the bonded list
     882              : !> \param atom_bond_list ...
     883              : !> \param mol_info ...
     884              : !> \param iatom ...
     885              : !> \param imol ...
     886              : !> \param my_mol_name ...
     887              : !> \param mol_name ...
     888              : !> \author Joost 05.2006
     889              : ! **************************************************************************************************
     890       763127 :    RECURSIVE SUBROUTINE spread_mol(atom_bond_list, mol_info, iatom, imol, &
     891              :                                    my_mol_name, mol_name)
     892              :       TYPE(array1_list_type), DIMENSION(:), INTENT(IN)   :: atom_bond_list
     893              :       INTEGER, DIMENSION(:), POINTER                     :: mol_info
     894              :       INTEGER, INTENT(IN)                                :: iatom, imol, my_mol_name
     895              :       INTEGER, DIMENSION(:), POINTER                     :: mol_name
     896              : 
     897              :       INTEGER                                            :: atom_b, i
     898              : 
     899       763127 :       mol_info(iatom) = imol
     900      1795793 :       DO I = 1, SIZE(atom_bond_list(iatom)%array1)
     901      1032666 :          atom_b = atom_bond_list(iatom)%array1(I)
     902              :          ! In this way we're really sure that all atoms belong to the same
     903              :          ! molecule. This should correct possible errors in the generation of
     904              :          ! the bond list..
     905      1795793 :          IF (mol_info(atom_b) == -1 .AND. my_mol_name == mol_name(atom_b)) THEN
     906       432343 :             CALL spread_mol(atom_bond_list, mol_info, atom_b, imol, my_mol_name, mol_name)
     907       432343 :             IF (mol_info(atom_b) /= imol) CPABORT("internal error")
     908              :          END IF
     909              :       END DO
     910       763127 :    END SUBROUTINE spread_mol
     911              : 
     912              : ! **************************************************************************************************
     913              : !> \brief Use info from periodic table and set atm_mass
     914              : !> \param topology ...
     915              : !> \param subsys_section ...
     916              : ! **************************************************************************************************
     917         9791 :    SUBROUTINE topology_set_atm_mass(topology, subsys_section)
     918              :       TYPE(topology_parameters_type), INTENT(INOUT)      :: topology
     919              :       TYPE(section_vals_type), POINTER                   :: subsys_section
     920              : 
     921              :       CHARACTER(len=*), PARAMETER :: routineN = 'topology_set_atm_mass'
     922              : 
     923              :       CHARACTER(LEN=2)                                   :: upper_sym_1
     924              :       CHARACTER(LEN=default_string_length)               :: atmname_upper
     925              :       CHARACTER(LEN=default_string_length), &
     926         9791 :          DIMENSION(:), POINTER                           :: keyword
     927              :       INTEGER                                            :: handle, i, i_rep, iatom, ielem_found, &
     928              :                                                             iw, n_rep, natom
     929              :       LOGICAL                                            :: user_defined
     930         9791 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mass
     931              :       TYPE(atom_info_type), POINTER                      :: atom_info
     932              :       TYPE(cp_logger_type), POINTER                      :: logger
     933              :       TYPE(section_vals_type), POINTER                   :: kind_section
     934              : 
     935         9791 :       NULLIFY (logger)
     936        19582 :       logger => cp_get_default_logger()
     937              :       iw = cp_print_key_unit_nr(logger, subsys_section, "PRINT%TOPOLOGY_INFO/UTIL_INFO", &
     938         9791 :                                 extension=".subsysLog")
     939         9791 :       CALL timeset(routineN, handle)
     940              : 
     941         9791 :       atom_info => topology%atom_info
     942         9791 :       natom = topology%natoms
     943              : 
     944              :       ! Available external info
     945         9791 :       kind_section => section_vals_get_subs_vals(subsys_section, "KIND")
     946         9791 :       CALL section_vals_get(kind_section, n_repetition=n_rep)
     947        25657 :       ALLOCATE (keyword(n_rep))
     948        25657 :       ALLOCATE (mass(n_rep))
     949        21998 :       mass = HUGE(0.0_dp)
     950        21998 :       DO i_rep = 1, n_rep
     951              :          CALL section_vals_val_get(kind_section, "_SECTION_PARAMETERS_", &
     952        12207 :                                    c_val=keyword(i_rep), i_rep_section=i_rep)
     953        12207 :          CALL uppercase(keyword(i_rep))
     954              :          CALL section_vals_val_get(kind_section, i_rep_section=i_rep, &
     955        12207 :                                    keyword_name="MASS", n_rep_val=i)
     956        12207 :          IF (i > 0) CALL section_vals_val_get(kind_section, i_rep_section=i_rep, &
     957        22096 :                                               keyword_name="MASS", r_val=mass(i_rep))
     958              :       END DO
     959              :       !
     960       288929 :       DO iatom = 1, natom
     961              :          !If we reach this point then we've definitely identified the element..
     962              :          !Let's look if an external mass has been defined..
     963       279138 :          user_defined = .FALSE.
     964       392136 :          DO i = 1, SIZE(keyword)
     965       113596 :             atmname_upper = id2str(atom_info%id_atmname(iatom))
     966       113596 :             CALL uppercase(atmname_upper)
     967       392136 :             IF (TRIM(atmname_upper) == TRIM(keyword(i)) .AND. mass(i) /= HUGE(0.0_dp)) THEN
     968          598 :                atom_info%atm_mass(iatom) = mass(i)
     969              :                user_defined = .TRUE.
     970              :                EXIT
     971              :             END IF
     972              :          END DO
     973              :          ! If name didn't match let's try with the element
     974       278540 :          IF (.NOT. user_defined) THEN
     975       278540 :             upper_sym_1 = TRIM(id2str(atom_info%id_element(iatom)))
     976       278540 :             CALL get_ptable_info(symbol=upper_sym_1, ielement=ielem_found, amass=atom_info%atm_mass(iatom))
     977              :          END IF
     978       280542 :          IF (iw > 0) WRITE (iw, '(7X,A,A5,A,F12.5)') "In topology_set_atm_mass :: element = ", &
     979        12599 :             id2str(atom_info%id_element(iatom)), " a_mass ", atom_info%atm_mass(iatom)
     980              :       END DO
     981         9791 :       DEALLOCATE (keyword)
     982         9791 :       DEALLOCATE (mass)
     983              : 
     984         9791 :       CALL timestop(handle)
     985              :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
     986         9791 :                                         "PRINT%TOPOLOGY_INFO/UTIL_INFO")
     987              : 
     988        29373 :    END SUBROUTINE topology_set_atm_mass
     989              : 
     990              : ! **************************************************************************************************
     991              : !> \brief Check and verify that all molecules of the same kind are bonded the same
     992              : !> \param topology ...
     993              : !> \param subsys_section ...
     994              : ! **************************************************************************************************
     995         9736 :    SUBROUTINE topology_molecules_check(topology, subsys_section)
     996              :       TYPE(topology_parameters_type), INTENT(INOUT)      :: topology
     997              :       TYPE(section_vals_type), POINTER                   :: subsys_section
     998              : 
     999              :       CHARACTER(len=*), PARAMETER :: routineN = 'topology_molecules_check'
    1000              : 
    1001              :       INTEGER                                            :: counter, first, first_loc, handle, i, &
    1002              :                                                             iatom, iw, k, loc_counter, mol_num, &
    1003              :                                                             mol_typ, n, natom
    1004              :       LOGICAL                                            :: icheck_num, icheck_typ
    1005         9736 :       TYPE(array1_list_type), ALLOCATABLE, DIMENSION(:)  :: atom_bond_list
    1006              :       TYPE(atom_info_type), POINTER                      :: atom_info
    1007              :       TYPE(connectivity_info_type), POINTER              :: conn_info
    1008              :       TYPE(cp_logger_type), POINTER                      :: logger
    1009              : 
    1010         9736 :       CALL timeset(routineN, handle)
    1011              : 
    1012         9736 :       NULLIFY (logger)
    1013         9736 :       logger => cp_get_default_logger()
    1014              :       iw = cp_print_key_unit_nr(logger, subsys_section, "PRINT%TOPOLOGY_INFO/UTIL_INFO", &
    1015         9736 :                                 extension=".subsysLog")
    1016              : 
    1017         9736 :       atom_info => topology%atom_info
    1018         9736 :       conn_info => topology%conn_info
    1019         9736 :       natom = topology%natoms
    1020              : 
    1021         9736 :       IF (iw > 0) THEN
    1022              :          WRITE (UNIT=iw, FMT="(/,T2,A)") &
    1023           26 :             "FORCEFIELD| Checking consistency of the generated molecules"
    1024              :       END IF
    1025              : 
    1026       780065 :       ALLOCATE (atom_bond_list(natom))
    1027              : 
    1028       760593 :       DO I = 1, natom
    1029       760593 :          ALLOCATE (atom_bond_list(I)%array1(0))
    1030              :       END DO
    1031         9736 :       N = 0
    1032         9736 :       IF (ASSOCIATED(conn_info%bond_a)) N = SIZE(conn_info%bond_a)
    1033         9736 :       CALL reorder_structure(atom_bond_list, conn_info%bond_a, conn_info%bond_b, N)
    1034              : 
    1035         9736 :       mol_typ = atom_info%map_mol_typ(1)
    1036         9736 :       mol_num = atom_info%map_mol_num(1)
    1037         9736 :       counter = 1
    1038         9736 :       loc_counter = 1
    1039         9736 :       first = 1
    1040         9736 :       first_loc = 1
    1041       750857 :       DO iatom = 2, natom
    1042       741121 :          icheck_num = (atom_info%map_mol_num(iatom) == mol_num)
    1043       741121 :          icheck_typ = (atom_info%map_mol_typ(iatom) == mol_typ)
    1044       741121 :          IF ((icheck_typ .AND. (.NOT. icheck_num)) .OR. (.NOT. icheck_typ)) THEN
    1045              :             !-----------------------------------------------------------------------------
    1046              :             ! 1. Check each molecule have the same number of atoms
    1047              :             !-----------------------------------------------------------------------------
    1048       288992 :             IF (counter /= loc_counter) THEN
    1049              :                CALL cp_abort(__LOCATION__, &
    1050              :                              "Different number of atoms for the same molecule kind found "// &
    1051              :                              "(molecule type = "//TRIM(ADJUSTL(cp_to_string(mol_typ)))// &
    1052              :                              ", molecule number = "//TRIM(ADJUSTL(cp_to_string(mol_num)))// &
    1053              :                              ", expected number of atoms = "// &
    1054              :                              TRIM(ADJUSTL(cp_to_string(counter)))// &
    1055              :                              ", number of atoms found = "// &
    1056            0 :                              TRIM(ADJUSTL(cp_to_string(loc_counter)))//").")
    1057              :             END IF
    1058              :          END IF
    1059       741121 :          IF (.NOT. icheck_typ) THEN
    1060       119861 :             first = iatom
    1061       119861 :             first_loc = iatom
    1062       119861 :             counter = 1
    1063       119861 :             loc_counter = 1
    1064       119861 :             mol_typ = atom_info%map_mol_typ(iatom)
    1065              :          END IF
    1066       741121 :          IF (icheck_num) THEN
    1067       571322 :             IF (icheck_typ) loc_counter = loc_counter + 1
    1068              :             !-----------------------------------------------------------------------------
    1069              :             ! 2. Check that each molecule has the same atom sequences
    1070              :             !-----------------------------------------------------------------------------
    1071       571322 :             IF (atom_info%id_atmname(iatom) /= &
    1072              :                 atom_info%id_atmname(first + loc_counter - 1)) THEN
    1073              :                CALL cp_abort(__LOCATION__, &
    1074              :                              "Different atom names for the same molecule kind found "// &
    1075              :                              "(atom number = "//TRIM(ADJUSTL(cp_to_string(iatom)))// &
    1076              :                              ", molecule type = "//TRIM(ADJUSTL(cp_to_string(mol_typ)))// &
    1077              :                              ", molecule number = "//TRIM(ADJUSTL(cp_to_string(mol_num)))// &
    1078              :                              ", expected atom name = "// &
    1079              :                              TRIM(ADJUSTL(id2str(atom_info%id_atmname(first + loc_counter - 1))))// &
    1080              :                              ", atom name found = "// &
    1081            0 :                              TRIM(ADJUSTL(id2str(atom_info%id_atmname(iatom))))//").")
    1082              :             END IF
    1083              :             !-----------------------------------------------------------------------------
    1084              :             ! 3. Check that each molecule have the same bond sequences
    1085              :             !-----------------------------------------------------------------------------
    1086       571322 :             IF (SIZE(atom_bond_list(iatom)%array1) /= SIZE(atom_bond_list(first + loc_counter - 1)%array1)) THEN
    1087              :                CALL cp_abort(__LOCATION__, &
    1088              :                              "Different number of bonds for the same molecule kind found "// &
    1089              :                              "(molecule type = "//TRIM(ADJUSTL(cp_to_string(mol_typ)))// &
    1090              :                              ", molecule number = "//TRIM(ADJUSTL(cp_to_string(mol_num)))// &
    1091              :                              ", expected number of bonds = "// &
    1092              :                              TRIM(ADJUSTL(cp_to_string(SIZE(atom_bond_list(first + loc_counter - 1)%array1))))// &
    1093              :                              ", number of bonds found = "// &
    1094              :                              TRIM(ADJUSTL(cp_to_string(SIZE(atom_bond_list(iatom)%array1))))// &
    1095            0 :                              "). Check the connectivity of your system.")
    1096              :             END IF
    1097      1279072 :             DO k = 1, SIZE(atom_bond_list(iatom)%array1)
    1098      1023103 :                IF (ALL(atom_bond_list(first + loc_counter - 1)%array1 - first /= &
    1099       571322 :                        atom_bond_list(iatom)%array1(k) - first_loc)) THEN
    1100              :                   CALL cp_abort(__LOCATION__, &
    1101              :                                 "Different sequence of bonds for the same molecule kind found "// &
    1102              :                                 "(molecule type = "//TRIM(ADJUSTL(cp_to_string(mol_typ)))// &
    1103              :                                 ", molecule number = "//TRIM(ADJUSTL(cp_to_string(mol_num)))// &
    1104            0 :                                 "). Check the connectivity of your system.")
    1105              :                END IF
    1106              :             END DO
    1107              :          ELSE
    1108       169799 :             mol_num = atom_info%map_mol_num(iatom)
    1109       169799 :             loc_counter = 1
    1110       169799 :             first_loc = iatom
    1111              :          END IF
    1112       750857 :          IF (mol_num == 1 .AND. icheck_typ) counter = counter + 1
    1113              :       END DO
    1114              : 
    1115         9736 :       IF (iw > 0) THEN
    1116              :          WRITE (UNIT=iw, FMT="(T2,A)") &
    1117           26 :             "FORCEFIELD| Consistency check for molecules completed"
    1118              :       END IF
    1119              : 
    1120       760593 :       DO I = 1, natom
    1121       760593 :          DEALLOCATE (atom_bond_list(I)%array1)
    1122              :       END DO
    1123         9736 :       DEALLOCATE (atom_bond_list)
    1124              : 
    1125              :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
    1126         9736 :                                         "PRINT%TOPOLOGY_INFO/UTIL_INFO")
    1127              : 
    1128         9736 :       CALL timestop(handle)
    1129              : 
    1130        19472 :    END SUBROUTINE topology_molecules_check
    1131              : 
    1132              : ! **************************************************************************************************
    1133              : !> \brief Check and returns the ELEMENT label
    1134              : !> \param element_in ...
    1135              : !> \param atom_name_in ...
    1136              : !> \param element_out ...
    1137              : !> \param subsys_section ...
    1138              : !> \param use_mm_map_first ...
    1139              : !> \par History
    1140              : !>      12.2005 created [teo]
    1141              : !> \author Teodoro Laino
    1142              : ! **************************************************************************************************
    1143        54934 :    SUBROUTINE check_subsys_element(element_in, atom_name_in, element_out, subsys_section, use_mm_map_first)
    1144              :       CHARACTER(len=*), INTENT(IN)                       :: element_in, atom_name_in
    1145              :       CHARACTER(len=default_string_length), INTENT(OUT)  :: element_out
    1146              :       TYPE(section_vals_type), POINTER                   :: subsys_section
    1147              :       LOGICAL                                            :: use_mm_map_first
    1148              : 
    1149              :       CHARACTER(len=default_string_length)               :: atom_name, element_symbol, keyword
    1150              :       INTEGER                                            :: i, i_rep, n_rep
    1151              :       LOGICAL                                            :: defined_kind_section, found, in_ptable
    1152              :       TYPE(section_vals_type), POINTER                   :: kind_section
    1153              : 
    1154        27467 :       found = .FALSE.
    1155        27467 :       element_symbol = element_in
    1156        27467 :       atom_name = atom_name_in
    1157        27467 :       element_out = ""
    1158        27467 :       defined_kind_section = .FALSE.
    1159              : 
    1160              :       ! First check if a KIND section is overriding the element
    1161              :       ! definition
    1162        27467 :       CALL uppercase(atom_name)
    1163        27467 :       kind_section => section_vals_get_subs_vals(subsys_section, "KIND")
    1164        27467 :       CALL section_vals_get(kind_section, n_repetition=n_rep)
    1165        81266 :       DO i_rep = 1, n_rep
    1166              :          CALL section_vals_val_get(kind_section, "_SECTION_PARAMETERS_", &
    1167        55045 :                                    c_val=keyword, i_rep_section=i_rep)
    1168        55045 :          CALL uppercase(keyword)
    1169        81266 :          IF (TRIM(keyword) == TRIM(atom_name)) THEN
    1170              :             CALL section_vals_val_get(kind_section, i_rep_section=i_rep, &
    1171        14733 :                                       keyword_name="ELEMENT", n_rep_val=i)
    1172        14733 :             IF (i > 0) THEN
    1173              :                CALL section_vals_val_get(kind_section, i_rep_section=i_rep, &
    1174         1246 :                                          keyword_name="ELEMENT", c_val=element_symbol)
    1175              :                defined_kind_section = .TRUE.
    1176              :                EXIT
    1177              :             ELSE
    1178        13487 :                element_symbol = element_in
    1179              :                defined_kind_section = .TRUE.
    1180              :             END IF
    1181              :          END IF
    1182              :       END DO
    1183              : 
    1184              :       ! Let's check the validity of the element so far stored..
    1185              :       ! if we are not having a connectivity file, we must first match against the ptable.
    1186              :       ! this helps to resolve Ca/CA (calcium and Calpha) or Cn/CN7 (Coppernicum (112) CN) conflicts
    1187              :       ! so, in the presence of connectivity CA will be 'C', while in the absence of connectivity CA will be 'Ca'
    1188        26221 :       IF (defined_kind_section .OR. .NOT. use_mm_map_first) THEN
    1189              :          ! lengths larger than 2 should not match, because 'trailing' characters are ignored.
    1190        22987 :          in_ptable = .FALSE.
    1191        22987 :          IF (LEN_TRIM(element_symbol) <= 2) CALL get_ptable_info(element_symbol, found=in_ptable)
    1192        22987 :          IF (in_ptable) THEN
    1193        22895 :             element_out = TRIM(element_symbol)
    1194        22895 :             found = .TRUE.
    1195              :          END IF
    1196              :       END IF
    1197              : 
    1198              :       ! This is clearly a user error
    1199        27467 :       IF (.NOT. found .AND. defined_kind_section) &
    1200              :          CALL cp_abort(__LOCATION__, "Element <"//TRIM(element_symbol)// &
    1201              :                        "> provided for KIND <"//TRIM(atom_name_in)//"> "// &
    1202              :                        "which cannot be mapped with any standard element label. Please correct your "// &
    1203            0 :                        "input file!")
    1204              : 
    1205              :       ! Last chance.. are these atom_kinds of AMBER or CHARMM or GROMOS FF ?
    1206        27467 :       CALL uppercase(element_symbol)
    1207        27467 :       IF ((.NOT. found) .AND. (ASSOCIATED(amber_map))) THEN
    1208              :          ! First we go through the AMBER library
    1209       145742 :          DO i = 1, SIZE(amber_map%kind)
    1210       145742 :             IF (element_symbol == amber_map%kind(i)) THEN
    1211              :                found = .TRUE.
    1212              :                EXIT
    1213              :             END IF
    1214              :          END DO
    1215         4572 :          IF (found) THEN
    1216         4136 :             element_out = amber_map%element(i)
    1217              :          END IF
    1218              :       END IF
    1219         4572 :       IF ((.NOT. found) .AND. (ASSOCIATED(charmm_map))) THEN
    1220              :          ! Then we go through the CHARMM library
    1221        39242 :          DO i = 1, SIZE(charmm_map%kind)
    1222        39242 :             IF (element_symbol == charmm_map%kind(i)) THEN
    1223              :                found = .TRUE.
    1224              :                EXIT
    1225              :             END IF
    1226              :          END DO
    1227          436 :          IF (found) THEN
    1228          196 :             element_out = charmm_map%element(i)
    1229              :          END IF
    1230              :       END IF
    1231          436 :       IF ((.NOT. found) .AND. (ASSOCIATED(gromos_map))) THEN
    1232              :          ! Then we go through the GROMOS library
    1233         5520 :          DO i = 1, SIZE(gromos_map%kind)
    1234         5520 :             IF (element_symbol == gromos_map%kind(i)) THEN
    1235              :                found = .TRUE.
    1236              :                EXIT
    1237              :             END IF
    1238              :          END DO
    1239          240 :          IF (found) THEN
    1240            0 :             element_out = gromos_map%element(i)
    1241              :          END IF
    1242              :       END IF
    1243              : 
    1244              :       ! final check. We has a connectivity, so we first tried to match against the ff_maps, but the element was not there.
    1245              :       ! Try again the periodic table.
    1246            0 :       IF (.NOT. found) THEN
    1247          240 :          in_ptable = .FALSE.
    1248          240 :          IF (LEN_TRIM(element_symbol) <= 2) CALL get_ptable_info(element_symbol, found=in_ptable)
    1249          240 :          IF (in_ptable) THEN
    1250          240 :             element_out = TRIM(element_symbol)
    1251              :             found = .TRUE.
    1252              :          END IF
    1253              :       END IF
    1254              : 
    1255              :       ! If no element is found the job stops here.
    1256            0 :       IF (.NOT. found) THEN
    1257              :          CALL cp_abort(__LOCATION__, &
    1258              :                        " Unknown element for KIND <"//TRIM(atom_name_in)//">."// &
    1259              :                        " This problem can be fixed specifying properly elements in PDB"// &
    1260              :                        " or specifying a KIND section or getting in touch with one of"// &
    1261            0 :                        " the developers!")
    1262              :       END IF
    1263              : 
    1264        27467 :    END SUBROUTINE check_subsys_element
    1265              : 
    1266            0 : END MODULE topology_util
        

Generated by: LCOV version 2.0-1