LCOV - code coverage report
Current view: top level - src - topology_coordinate_util.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:c24029e) Lines: 97.8 % 418 409
Test Date: 2026-07-04 06:36:57 Functions: 100.0 % 2 2

            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              : !>     jgh (23-05-2004) Last atom of molecule information added
      12              : ! **************************************************************************************************
      13              : MODULE topology_coordinate_util
      14              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      15              :                                               get_atomic_kind,&
      16              :                                               set_atomic_kind
      17              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      18              :                                               cp_logger_type
      19              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      20              :                                               cp_print_key_unit_nr
      21              :    USE exclusion_types,                 ONLY: exclusion_type
      22              :    USE external_potential_types,        ONLY: allocate_potential,&
      23              :                                               fist_potential_type,&
      24              :                                               get_potential,&
      25              :                                               set_potential
      26              :    USE input_constants,                 ONLY: do_fist,&
      27              :                                               do_skip_12,&
      28              :                                               do_skip_13,&
      29              :                                               do_skip_14
      30              :    USE input_section_types,             ONLY: section_vals_get,&
      31              :                                               section_vals_get_subs_vals,&
      32              :                                               section_vals_type,&
      33              :                                               section_vals_val_get
      34              :    USE kinds,                           ONLY: default_string_length,&
      35              :                                               dp
      36              :    USE memory_utilities,                ONLY: reallocate
      37              :    USE molecule_kind_types,             ONLY: atom_type,&
      38              :                                               get_molecule_kind,&
      39              :                                               molecule_kind_type,&
      40              :                                               set_molecule_kind
      41              :    USE molecule_types,                  ONLY: get_molecule,&
      42              :                                               molecule_type
      43              :    USE particle_types,                  ONLY: allocate_particle_set,&
      44              :                                               particle_type
      45              :    USE physcon,                         ONLY: massunit
      46              :    USE qmmm_types_low,                  ONLY: qmmm_env_mm_type
      47              :    USE string_table,                    ONLY: id2str,&
      48              :                                               s2s,&
      49              :                                               str2id
      50              :    USE topology_types,                  ONLY: atom_info_type,&
      51              :                                               connectivity_info_type,&
      52              :                                               topology_parameters_type
      53              :    USE topology_util,                   ONLY: array1_list_type,&
      54              :                                               reorder_structure
      55              : #include "./base/base_uses.f90"
      56              : 
      57              :    IMPLICIT NONE
      58              : 
      59              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'topology_coordinate_util'
      60              : 
      61              :    PRIVATE
      62              :    PUBLIC :: topology_coordinate_pack
      63              : 
      64              : CONTAINS
      65              : 
      66              : ! **************************************************************************************************
      67              : !> \brief Take info readin from different file format and stuff it into
      68              : !>      compatible data structure in cp2k
      69              : !> \param particle_set ...
      70              : !> \param atomic_kind_set ...
      71              : !> \param molecule_kind_set ...
      72              : !> \param molecule_set ...
      73              : !> \param topology ...
      74              : !> \param qmmm ...
      75              : !> \param qmmm_env ...
      76              : !> \param subsys_section ...
      77              : !> \param force_env_section ...
      78              : !> \param exclusions ...
      79              : !> \param ignore_outside_box ...
      80              : !> \par History
      81              : !>      Teodoro Laino - modified in order to optimize the list of molecules
      82              : !>                      to build the exclusion lists
      83              : ! **************************************************************************************************
      84        11404 :    SUBROUTINE topology_coordinate_pack(particle_set, atomic_kind_set, &
      85              :                                        molecule_kind_set, molecule_set, topology, qmmm, qmmm_env, &
      86              :                                        subsys_section, force_env_section, exclusions, ignore_outside_box)
      87              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
      88              :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
      89              :       TYPE(molecule_kind_type), DIMENSION(:), POINTER    :: molecule_kind_set
      90              :       TYPE(molecule_type), DIMENSION(:), POINTER         :: molecule_set
      91              :       TYPE(topology_parameters_type), INTENT(INOUT)      :: topology
      92              :       LOGICAL, INTENT(IN), OPTIONAL                      :: qmmm
      93              :       TYPE(qmmm_env_mm_type), OPTIONAL, POINTER          :: qmmm_env
      94              :       TYPE(section_vals_type), POINTER                   :: subsys_section, force_env_section
      95              :       TYPE(exclusion_type), DIMENSION(:), OPTIONAL, &
      96              :          POINTER                                         :: exclusions
      97              :       LOGICAL, INTENT(IN), OPTIONAL                      :: ignore_outside_box
      98              : 
      99              :       CHARACTER(len=*), PARAMETER :: routineN = 'topology_coordinate_pack'
     100              : 
     101              :       CHARACTER(LEN=default_string_length)               :: atmname, err
     102              :       INTEGER                                            :: atom_i, atom_j, counter, dim0, dim1, &
     103              :                                                             dim2, dim3, first, handle, handle2, i, &
     104              :                                                             iatom, ikind, iw, j, k, last, &
     105              :                                                             method_name_id, n, natom
     106        11404 :       INTEGER, DIMENSION(:), POINTER                     :: iatomlist, id_element, id_work, kind_of, &
     107        11404 :                                                             list, list2, molecule_list, &
     108        11404 :                                                             natom_of_kind, wlist
     109        11404 :       INTEGER, DIMENSION(:, :), POINTER                  :: pairs
     110              :       LOGICAL :: autogen, check, disable_exclusion_lists, do_center, explicit, found, &
     111              :          my_ignore_outside_box, my_qmmm, present_12_excl_ei_list, present_12_excl_vdw_list
     112              :       REAL(KIND=dp)                                      :: bounds(2, 3), cdims(3), dims(3), qeff, &
     113              :                                                             vec(3)
     114        11404 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: charge, cpoint, mass
     115        11404 :       TYPE(array1_list_type), DIMENSION(:), POINTER      :: ex_bend_list, ex_bond_list, &
     116        11404 :                                                             ex_bond_list_ei, ex_bond_list_vdw, &
     117        11404 :                                                             ex_onfo_list
     118              :       TYPE(atom_info_type), POINTER                      :: atom_info
     119        11404 :       TYPE(atom_type), DIMENSION(:), POINTER             :: atom_list
     120              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
     121              :       TYPE(connectivity_info_type), POINTER              :: conn_info
     122              :       TYPE(cp_logger_type), POINTER                      :: logger
     123              :       TYPE(fist_potential_type), POINTER                 :: fist_potential
     124              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
     125              :       TYPE(molecule_type), POINTER                       :: molecule
     126              :       TYPE(section_vals_type), POINTER                   :: exclude_section, topology_section
     127              : 
     128        11404 :       NULLIFY (logger)
     129        22808 :       logger => cp_get_default_logger()
     130              :       iw = cp_print_key_unit_nr(logger, subsys_section, "PRINT%TOPOLOGY_INFO/UTIL_INFO", &
     131        11404 :                                 extension=".subsysLog")
     132        11404 :       topology_section => section_vals_get_subs_vals(subsys_section, "TOPOLOGY")
     133        11404 :       CALL timeset(routineN, handle)
     134              : 
     135        11404 :       my_qmmm = .FALSE.
     136        11404 :       IF (PRESENT(qmmm) .AND. PRESENT(qmmm_env)) my_qmmm = qmmm
     137        11404 :       atom_info => topology%atom_info
     138        11404 :       conn_info => topology%conn_info
     139              :       !-----------------------------------------------------------------------------
     140              :       !-----------------------------------------------------------------------------
     141              :       ! 1. Determine topology%[natom_type,atom_names] and save mass(natom_type)
     142              :       !    and element(natom_type)
     143              :       !-----------------------------------------------------------------------------
     144        11404 :       CALL timeset(routineN//'_1', handle2)
     145        11404 :       counter = 0
     146        11404 :       NULLIFY (id_work, mass, id_element, charge)
     147        34212 :       ALLOCATE (id_work(topology%natoms))
     148        34212 :       ALLOCATE (mass(topology%natoms))
     149        22808 :       ALLOCATE (id_element(topology%natoms))
     150        22808 :       ALLOCATE (charge(topology%natoms))
     151       776609 :       id_work = str2id(s2s(""))
     152        11404 :       IF (iw > 0) WRITE (iw, *) "molecule_kind_set ::", SIZE(molecule_kind_set)
     153       157647 :       DO i = 1, SIZE(molecule_kind_set)
     154       146243 :          j = molecule_kind_set(i)%molecule_list(1)
     155       146243 :          molecule => molecule_set(j)
     156       146243 :          molecule_kind => molecule_set(j)%molecule_kind
     157       146243 :          IF (iw > 0) WRITE (iw, *) "molecule number ::", j, " has molecule kind number ::", i
     158              :          CALL get_molecule_kind(molecule_kind=molecule_kind, &
     159       146243 :                                 natom=natom, atom_list=atom_list)
     160              :          CALL get_molecule(molecule=molecule, &
     161       146243 :                            first_atom=first, last_atom=last)
     162       146243 :          IF (iw > 0) WRITE (iw, *) "boundaries of molecules (first, last) ::", first, last
     163       563846 :          DO j = 1, natom
     164     18760839 :             IF (.NOT. ANY(id_work(1:counter) == atom_list(j)%id_name)) THEN
     165        27483 :                counter = counter + 1
     166        27483 :                id_work(counter) = atom_list(j)%id_name
     167        27483 :                mass(counter) = atom_info%atm_mass(first + j - 1)
     168        27483 :                id_element(counter) = atom_info%id_element(first + j - 1)
     169        27483 :                charge(counter) = atom_info%atm_charge(first + j - 1)
     170        27483 :                IF (iw > 0) WRITE (iw, '(7X,A,1X,A5,F10.5,5X,A2,5X,F10.5)') &
     171           84 :                   "NEW ATOMIC KIND", id2str(id_work(counter)), mass(counter), id2str(id_element(counter)), charge(counter)
     172              :             ELSE
     173     18438393 :                found = .FALSE.
     174     18438393 :                DO k = 1, counter
     175     18438393 :                   IF ((id_work(k) == atom_list(j)%id_name) .AND. (charge(k) == atom_info%atm_charge(first + j - 1))) THEN
     176              :                      found = .TRUE.
     177              :                      EXIT
     178              :                   END IF
     179              :                END DO
     180       232473 :                IF (.NOT. found) THEN
     181          524 :                   counter = counter + 1
     182          524 :                   id_work(counter) = atom_list(j)%id_name
     183          524 :                   mass(counter) = atom_info%atm_mass(first + j - 1)
     184          524 :                   id_element(counter) = atom_info%id_element(first + j - 1)
     185          524 :                   charge(counter) = atom_info%atm_charge(first + j - 1)
     186          524 :                   IF (iw > 0) WRITE (iw, '(7X,A,1X,A5,F10.5,5X,A2,5X,F10.5)') &
     187            0 :                      "NEW ATOMIC KIND", id2str(id_work(counter)), mass(counter), id2str(id_element(counter)), charge(counter)
     188              :                END IF
     189              :             END IF
     190              :          END DO
     191              :       END DO
     192        11404 :       topology%natom_type = counter
     193        34212 :       ALLOCATE (atom_info%id_atom_names(topology%natom_type))
     194        39411 :       DO k = 1, counter
     195        39411 :          atom_info%id_atom_names(k) = id_work(k)
     196              :       END DO
     197        11404 :       DEALLOCATE (id_work)
     198        11404 :       CALL reallocate(mass, 1, counter)
     199        11404 :       CALL reallocate(id_element, 1, counter)
     200        11404 :       CALL reallocate(charge, 1, counter)
     201        11404 :       IF (iw > 0) &
     202           27 :          WRITE (iw, '(5X,A,I3)') "Total Number of Atomic Kinds = ", topology%natom_type
     203        11404 :       CALL timestop(handle2)
     204              : 
     205              :       !-----------------------------------------------------------------------------
     206              :       !-----------------------------------------------------------------------------
     207              :       ! 2. Allocate the data structure for the atomic kind information
     208              :       !-----------------------------------------------------------------------------
     209        11404 :       CALL timeset(routineN//'_2', handle2)
     210        11404 :       NULLIFY (atomic_kind_set)
     211        62219 :       ALLOCATE (atomic_kind_set(topology%natom_type))
     212        11404 :       CALL timestop(handle2)
     213              : 
     214              :       !-----------------------------------------------------------------------------
     215              :       !-----------------------------------------------------------------------------
     216              :       ! 3.  Allocate the data structure for the atomic information
     217              :       !-----------------------------------------------------------------------------
     218        11404 :       CALL timeset(routineN//'_3', handle2)
     219        11404 :       NULLIFY (particle_set)
     220        11404 :       CALL allocate_particle_set(particle_set, topology%natoms)
     221        11404 :       CALL timestop(handle2)
     222              : 
     223              :       !-----------------------------------------------------------------------------
     224              :       !-----------------------------------------------------------------------------
     225              :       ! 4. Set the atomic_kind_set(ikind)%[name,kind_number,mass]
     226              :       !-----------------------------------------------------------------------------
     227        11404 :       CALL timeset(routineN//'_4', handle2)
     228        39411 :       DO i = 1, topology%natom_type
     229        28007 :          atomic_kind => atomic_kind_set(i)
     230        28007 :          mass(i) = mass(i)*massunit
     231              :          CALL set_atomic_kind(atomic_kind=atomic_kind, &
     232              :                               kind_number=i, &
     233              :                               name=id2str(atom_info%id_atom_names(i)), &
     234              :                               element_symbol=id2str(id_element(i)), &
     235        28007 :                               mass=mass(i))
     236        39411 :          IF (iw > 0) THEN
     237           84 :             WRITE (iw, '(A,I5,A,I5,4A)') "Atomic Kind n.:", i, " out of:", topology%natom_type, &
     238           84 :                " name:   ", TRIM(id2str(atom_info%id_atom_names(i))), "   element:   ", &
     239          168 :                TRIM(id2str(id_element(i)))
     240              :          END IF
     241              :       END DO
     242        11404 :       DEALLOCATE (mass)
     243        11404 :       DEALLOCATE (id_element)
     244        11404 :       CALL timestop(handle2)
     245              : 
     246              :       !-----------------------------------------------------------------------------
     247              :       !-----------------------------------------------------------------------------
     248              :       ! 5. Determine number of atom of each kind (ie natom_of_kind and kind_of)
     249              :       !-----------------------------------------------------------------------------
     250        11404 :       CALL timeset(routineN//'_5', handle2)
     251        34212 :       ALLOCATE (kind_of(topology%natoms))
     252        34212 :       ALLOCATE (natom_of_kind(topology%natom_type))
     253       776609 :       kind_of(:) = 0
     254        39411 :       natom_of_kind(:) = 0
     255        39411 :       DO i = 1, topology%natom_type
     256     37106419 :          DO j = 1, topology%natoms
     257     37095015 :             IF ((atom_info%id_atom_names(i) == atom_info%id_atmname(j)) .AND. (charge(i) == atom_info%atm_charge(j))) THEN
     258       765205 :                natom_of_kind(i) = natom_of_kind(i) + 1
     259       765205 :                IF (kind_of(j) == 0) kind_of(j) = i
     260              :             END IF
     261              :          END DO
     262              :       END DO
     263       776609 :       IF (ANY(kind_of == 0)) THEN
     264            0 :          DO i = 1, topology%natoms
     265            0 :             IF (kind_of(i) == 0) THEN
     266            0 :                WRITE (err, "(1X,I5)") i
     267              :             END IF
     268              :          END DO
     269              :          CALL cp_abort(__LOCATION__, &
     270              :                        "Two molecules have been defined as identical molecules but atoms "// &
     271            0 :                        "mismatch charges! Check these atoms:"//TRIM(err))
     272              :       END IF
     273        11404 :       CALL timestop(handle2)
     274              : 
     275              :       !-----------------------------------------------------------------------------
     276              :       !-----------------------------------------------------------------------------
     277              :       ! 6. Set the atom_kind_set(ikind)%[natom,atom_list]
     278              :       !-----------------------------------------------------------------------------
     279        11404 :       CALL timeset(routineN//'_6', handle2)
     280        39411 :       DO i = 1, topology%natom_type
     281        28007 :          atomic_kind => atomic_kind_set(i)
     282              :          NULLIFY (iatomlist)
     283        84021 :          ALLOCATE (iatomlist(natom_of_kind(i)))
     284        28007 :          counter = 0
     285     37095015 :          DO j = 1, topology%natoms
     286     37095015 :             IF (kind_of(j) == i) THEN
     287       765205 :                counter = counter + 1
     288       765205 :                iatomlist(counter) = j
     289              :             END IF
     290              :          END DO
     291        28007 :          IF (iw > 0) THEN
     292           84 :             WRITE (iw, '(A,I6,A)') "      Atomic kind ", i, " contains particles"
     293         1616 :             DO J = 1, SIZE(iatomlist)
     294         1616 :                IF (MOD(J, 5) == 0) THEN ! split long lines
     295          271 :                   WRITE (iw, '(I12)') iatomlist(J)
     296              :                ELSE
     297         1261 :                   WRITE (iw, '(I12)', ADVANCE="NO") iatomlist(J)
     298              :                END IF
     299              :             END DO
     300           84 :             WRITE (iw, *)
     301              :          END IF
     302              :          CALL set_atomic_kind(atomic_kind=atomic_kind, &
     303              :                               natom=natom_of_kind(i), &
     304        28007 :                               atom_list=iatomlist)
     305        39411 :          DEALLOCATE (iatomlist)
     306              :       END DO
     307        11404 :       DEALLOCATE (natom_of_kind)
     308        11404 :       CALL timestop(handle2)
     309              : 
     310              :       !-----------------------------------------------------------------------------
     311              :       !-----------------------------------------------------------------------------
     312              :       ! 7. Possibly center the coordinates and fill in coordinates in particle_set
     313              :       !-----------------------------------------------------------------------------
     314              :       CALL section_vals_val_get(subsys_section, &
     315        11404 :                                 "TOPOLOGY%CENTER_COORDINATES%_SECTION_PARAMETERS_", l_val=do_center)
     316        11404 :       CALL timeset(routineN//'_7a', handle2)
     317       776609 :       bounds(1, 1) = MINVAL(atom_info%r(1, :))
     318       776609 :       bounds(2, 1) = MAXVAL(atom_info%r(1, :))
     319              : 
     320       776609 :       bounds(1, 2) = MINVAL(atom_info%r(2, :))
     321       776609 :       bounds(2, 2) = MAXVAL(atom_info%r(2, :))
     322              : 
     323       776609 :       bounds(1, 3) = MINVAL(atom_info%r(3, :))
     324       776609 :       bounds(2, 3) = MAXVAL(atom_info%r(3, :))
     325              : 
     326        45616 :       dims = bounds(2, :) - bounds(1, :)
     327        11404 :       cdims(1) = topology%cell%hmat(1, 1)
     328        11404 :       cdims(2) = topology%cell%hmat(2, 2)
     329        11404 :       cdims(3) = topology%cell%hmat(3, 3)
     330        11404 :       IF (iw > 0) THEN
     331           27 :          WRITE (iw, '(A,3F12.6)') "System sizes: ", dims, "Cell sizes (diagonal): ", cdims
     332              :       END IF
     333        11404 :       check = .TRUE.
     334        45616 :       DO i = 1, 3
     335        45616 :          IF (topology%cell%perd(i) == 0) THEN
     336        12358 :             check = check .AND. (dims(i) < cdims(i))
     337              :          END IF
     338              :       END DO
     339        11404 :       my_ignore_outside_box = .FALSE.
     340        11404 :       IF (PRESENT(ignore_outside_box)) my_ignore_outside_box = ignore_outside_box
     341        11404 :       IF (.NOT. my_ignore_outside_box .AND. .NOT. check) &
     342              :          CALL cp_abort(__LOCATION__, &
     343              :                        "A non-periodic calculation has been requested but the system size "// &
     344            0 :                        "exceeds the cell size in at least one of the non-periodic directions!")
     345        11404 :       IF (do_center) THEN
     346              :          CALL section_vals_val_get(subsys_section, &
     347         2426 :                                    "TOPOLOGY%CENTER_COORDINATES%CENTER_POINT", explicit=explicit)
     348         2426 :          IF (explicit) THEN
     349              :             CALL section_vals_val_get(subsys_section, &
     350            0 :                                       "TOPOLOGY%CENTER_COORDINATES%CENTER_POINT", r_vals=cpoint)
     351            0 :             vec = cpoint
     352              :          ELSE
     353         9704 :             vec = cdims/2.0_dp
     354              :          END IF
     355         9704 :          dims = (bounds(2, :) + bounds(1, :))/2.0_dp - vec
     356              :       ELSE
     357         8978 :          dims = 0.0_dp
     358              :       END IF
     359        11404 :       CALL timestop(handle2)
     360        11404 :       CALL timeset(routineN//'_7b', handle2)
     361       776609 :       DO i = 1, topology%natoms
     362       765205 :          ikind = kind_of(i)
     363       765205 :          IF (iw > 0) THEN
     364         1532 :             WRITE (iw, *) "atom number :: ", i, "kind number ::", ikind
     365              :          END IF
     366       765205 :          particle_set(i)%atomic_kind => atomic_kind_set(ikind)
     367      5356435 :          particle_set(i)%r(:) = atom_info%r(:, i) - dims
     368       776609 :          particle_set(i)%atom_index = i
     369              :       END DO
     370        11404 :       CALL timestop(handle2)
     371        11404 :       DEALLOCATE (kind_of)
     372              : 
     373              :       !-----------------------------------------------------------------------------
     374              :       !-----------------------------------------------------------------------------
     375              :       ! 8. Fill in the exclusions%list_exclude_vdw
     376              :       ! 9. Fill in the exclusions%list_exclude_ei
     377              :       ! 10. Fill in the exclusions%list_onfo
     378              :       !-----------------------------------------------------------------------------
     379        11404 :       CALL timeset(routineN//'_89', handle2)
     380        11404 :       CALL section_vals_val_get(force_env_section, "METHOD", i_val=method_name_id)
     381              :       CALL section_vals_val_get(subsys_section, "TOPOLOGY%DISABLE_EXCLUSION_LISTS", &
     382        11404 :                                 l_val=disable_exclusion_lists)
     383        11404 :       IF ((method_name_id == do_fist) .AND. (.NOT. disable_exclusion_lists)) THEN
     384         2484 :          CPASSERT(PRESENT(exclusions))
     385         2484 :          natom = topology%natoms
     386              :          ! allocate exclusions. Most likely they would only be needed for the local_particles
     387       640278 :          ALLOCATE (exclusions(natom))
     388       635310 :          DO I = 1, natom
     389       632826 :             NULLIFY (exclusions(i)%list_exclude_vdw)
     390       632826 :             NULLIFY (exclusions(i)%list_exclude_ei)
     391       635310 :             NULLIFY (exclusions(i)%list_onfo)
     392              :          END DO
     393              :          ! Reorder bonds
     394       640278 :          ALLOCATE (ex_bond_list(natom))
     395       635310 :          DO I = 1, natom
     396       635310 :             ALLOCATE (ex_bond_list(I)%array1(0))
     397              :          END DO
     398         2484 :          N = 0
     399         2484 :          IF (ASSOCIATED(conn_info%bond_a)) THEN
     400         2484 :             N = SIZE(conn_info%bond_a)
     401         2484 :             CALL reorder_structure(ex_bond_list, conn_info%bond_a, conn_info%bond_b, N)
     402              :          END IF
     403              : 
     404              :          ! Check if a list of 1-2 exclusion bonds is defined.. if not use all bonds
     405              :          NULLIFY (ex_bond_list_vdw, ex_bond_list_ei)
     406              :          ! VdW
     407         2484 :          exclude_section => section_vals_get_subs_vals(topology_section, "EXCLUDE_VDW_LIST")
     408         2484 :          CALL section_vals_get(exclude_section, explicit=explicit)
     409         2484 :          present_12_excl_vdw_list = .FALSE.
     410         2484 :          IF (explicit) present_12_excl_vdw_list = .TRUE.
     411              :          IF (present_12_excl_vdw_list) THEN
     412           40 :             ALLOCATE (ex_bond_list_vdw(natom))
     413           32 :             DO I = 1, natom
     414           32 :                ALLOCATE (ex_bond_list_vdw(I)%array1(0))
     415              :             END DO
     416              :             CALL setup_exclusion_list(exclude_section, "BOND", ex_bond_list, ex_bond_list_vdw, &
     417            8 :                                       particle_set)
     418              :          ELSE
     419         2476 :             ex_bond_list_vdw => ex_bond_list
     420              :          END IF
     421              :          ! EI
     422         2484 :          exclude_section => section_vals_get_subs_vals(topology_section, "EXCLUDE_EI_LIST")
     423         2484 :          CALL section_vals_get(exclude_section, explicit=explicit)
     424         2484 :          present_12_excl_ei_list = .FALSE.
     425         2484 :          IF (explicit) present_12_excl_ei_list = .TRUE.
     426              :          IF (present_12_excl_ei_list) THEN
     427           50 :             ALLOCATE (ex_bond_list_ei(natom))
     428           40 :             DO I = 1, natom
     429           40 :                ALLOCATE (ex_bond_list_ei(I)%array1(0))
     430              :             END DO
     431              :             CALL setup_exclusion_list(exclude_section, "BOND", ex_bond_list, ex_bond_list_ei, &
     432           10 :                                       particle_set)
     433              :          ELSE
     434         2474 :             ex_bond_list_ei => ex_bond_list
     435              :          END IF
     436              : 
     437              :          CALL section_vals_val_get(topology_section, "AUTOGEN_EXCLUDE_LISTS", &
     438         2484 :                                    l_val=autogen)
     439              :          ! Reorder bends
     440       637794 :          ALLOCATE (ex_bend_list(natom))
     441       635310 :          DO I = 1, natom
     442       635310 :             ALLOCATE (ex_bend_list(I)%array1(0))
     443              :          END DO
     444         2484 :          IF (autogen) THEN
     445              :             ! Construct autogenerated 1-3 pairs, i.e. all possible 1-3 pairs instead
     446              :             ! of only the bends that are present in the topology.
     447            4 :             ALLOCATE (pairs(0, 2))
     448            4 :             N = 0
     449           26 :             DO iatom = 1, natom
     450           62 :                DO i = 1, SIZE(ex_bond_list(iatom)%array1)
     451              :                   ! a neighboring atom of iatom:
     452           36 :                   atom_i = ex_bond_list(iatom)%array1(i)
     453           92 :                   DO j = 1, i - 1
     454              :                      ! another neighboring atom of iatom
     455           34 :                      atom_j = ex_bond_list(iatom)%array1(j)
     456              :                      ! It is only a true bend if there is no shorter path.
     457              :                      ! No need to check if i and j correspond to the same atom.
     458              :                      ! Check if i and j are not involved in a bond:
     459           34 :                      check = .FALSE.
     460           70 :                      DO counter = 1, SIZE(ex_bond_list(atom_i)%array1)
     461           70 :                         IF (ex_bond_list(atom_i)%array1(counter) == atom_j) THEN
     462              :                            check = .TRUE.
     463              :                            EXIT
     464              :                         END IF
     465              :                      END DO
     466           34 :                      IF (check) CYCLE
     467              :                      ! Add the genuine 1-3 pair
     468           34 :                      N = N + 1
     469           34 :                      IF (SIZE(pairs, dim=1) <= N) THEN
     470            8 :                         CALL reallocate(pairs, 1, N + 5, 1, 2)
     471              :                      END IF
     472           34 :                      pairs(N, 1) = atom_i
     473           70 :                      pairs(N, 2) = atom_j
     474              :                   END DO
     475              :                END DO
     476              :             END DO
     477            4 :             CALL reorder_structure(ex_bend_list, pairs(:, 1), pairs(:, 2), N)
     478            4 :             DEALLOCATE (pairs)
     479              :          ELSE
     480         2480 :             IF (ASSOCIATED(conn_info%theta_a)) THEN
     481         2480 :                N = SIZE(conn_info%theta_a)
     482         2480 :                CALL reorder_structure(ex_bend_list, conn_info%theta_a, conn_info%theta_c, N)
     483              :             END IF
     484              :          END IF
     485              : 
     486              :          ! Reorder onfo
     487       637794 :          ALLOCATE (ex_onfo_list(natom))
     488       635310 :          DO I = 1, natom
     489       635310 :             ALLOCATE (ex_onfo_list(I)%array1(0))
     490              :          END DO
     491         2484 :          IF (autogen) THEN
     492              :             ! Construct autogenerated 1-4 pairs, i.e. all possible 1-4 pairs instead
     493              :             ! of only the onfo's that are present in the topology.
     494            4 :             ALLOCATE (pairs(0, 2))
     495            4 :             N = 0
     496           26 :             DO iatom = 1, natom
     497           62 :                DO i = 1, SIZE(ex_bond_list(iatom)%array1)
     498              :                   ! a neighboring atom of iatom:
     499           36 :                   atom_i = ex_bond_list(iatom)%array1(i)
     500          130 :                   DO j = 1, SIZE(ex_bend_list(iatom)%array1)
     501              :                      ! a next neighboring atom of iatom:
     502           72 :                      atom_j = ex_bend_list(iatom)%array1(j)
     503              :                      ! It is only a true onfo if there is no shorter path.
     504              :                      ! check if i and j are not the same atom
     505           72 :                      IF (atom_i == atom_j) CYCLE
     506              :                      ! check if i and j are not involved in a bond
     507           72 :                      check = .FALSE.
     508          230 :                      DO counter = 1, SIZE(ex_bond_list(atom_i)%array1)
     509          230 :                         IF (ex_bond_list(atom_i)%array1(counter) == atom_j) THEN
     510              :                            check = .TRUE.
     511              :                            EXIT
     512              :                         END IF
     513              :                      END DO
     514           72 :                      IF (check) CYCLE
     515              :                      ! check if i and j are not involved in a bend
     516            4 :                      check = .FALSE.
     517            8 :                      DO counter = 1, SIZE(ex_bend_list(atom_i)%array1)
     518            8 :                         IF (ex_bend_list(atom_i)%array1(counter) == atom_j) THEN
     519              :                            check = .TRUE.
     520              :                            EXIT
     521              :                         END IF
     522              :                      END DO
     523            4 :                      IF (check) CYCLE
     524              :                      ! Add the true onfo.
     525            4 :                      N = N + 1
     526            4 :                      IF (SIZE(pairs, dim=1) <= N) THEN
     527            2 :                         CALL reallocate(pairs, 1, N + 5, 1, 2)
     528              :                      END IF
     529            4 :                      pairs(N, 1) = atom_i
     530          108 :                      pairs(N, 2) = atom_j
     531              :                   END DO
     532              :                END DO
     533              :             END DO
     534            4 :             CALL reorder_structure(ex_onfo_list, pairs(:, 1), pairs(:, 2), N)
     535            4 :             DEALLOCATE (pairs)
     536              :          ELSE
     537         2480 :             IF (ASSOCIATED(conn_info%onfo_a)) THEN
     538         2474 :                N = SIZE(conn_info%onfo_a)
     539         2474 :                CALL reorder_structure(ex_onfo_list, conn_info%onfo_a, conn_info%onfo_b, N)
     540              :             END IF
     541              :          END IF
     542              : 
     543              :          ! Build the exclusion (and onfo) list per atom.
     544       635310 :          DO iatom = 1, SIZE(particle_set)
     545              :             ! Setup exclusion list for VDW: always exclude itself
     546       632826 :             dim0 = 1
     547              :             ! exclude bond-neighbors (only if do_skip_12 .OR. do_skip_13 .OR. do_skip_14)
     548       632826 :             dim1 = 0
     549              :             IF (topology%exclude_vdw == do_skip_12 .OR. &
     550       632826 :                 topology%exclude_vdw == do_skip_13 .OR. &
     551       632232 :                 topology%exclude_vdw == do_skip_14) dim1 = SIZE(ex_bond_list_vdw(iatom)%array1)
     552       632826 :             dim1 = dim1 + dim0
     553       632826 :             dim2 = 0
     554       632826 :             IF (topology%exclude_vdw == do_skip_13 .OR. &
     555       631626 :                 topology%exclude_vdw == do_skip_14) dim2 = SIZE(ex_bend_list(iatom)%array1)
     556       632826 :             dim2 = dim1 + dim2
     557       632826 :             dim3 = 0
     558       632826 :             IF (topology%exclude_vdw == do_skip_14) dim3 = SIZE(ex_onfo_list(iatom)%array1)
     559       632826 :             dim3 = dim2 + dim3
     560       632826 :             IF (dim3 /= 0) THEN
     561       632826 :                NULLIFY (list, wlist)
     562      1898478 :                ALLOCATE (wlist(dim3))
     563      1265652 :                wlist(dim0:dim0) = iatom
     564      1604512 :                IF (dim1 > dim0) wlist(dim0 + 1:dim1) = ex_bond_list_vdw(iatom)%array1
     565      1156416 :                IF (dim2 > dim1) wlist(dim1 + 1:dim2) = ex_bend_list(iatom)%array1
     566       634374 :                IF (dim3 > dim2) wlist(dim2 + 1:dim3) = ex_onfo_list(iatom)%array1
     567              :                ! Get a unique list
     568      2129650 :                DO i = 1, SIZE(wlist) - 1
     569      1496824 :                   IF (wlist(i) == 0) CYCLE
     570      5431324 :                   DO j = i + 1, SIZE(wlist)
     571      4798568 :                      IF (wlist(j) == wlist(i)) wlist(j) = 0
     572              :                   END DO
     573              :                END DO
     574      2762476 :                dim3 = SIZE(wlist) - COUNT(wlist == 0)
     575      1898478 :                ALLOCATE (list(dim3))
     576       632826 :                j = 0
     577      2762476 :                DO i = 1, SIZE(wlist)
     578      2129650 :                   IF (wlist(i) == 0) CYCLE
     579      2043766 :                   j = j + 1
     580      2762476 :                   list(j) = wlist(i)
     581              :                END DO
     582       632826 :                DEALLOCATE (wlist)
     583              :                ! Unique list completed
     584       632826 :                NULLIFY (list2)
     585              :                IF ((topology%exclude_vdw == topology%exclude_ei) .AND. &
     586       632826 :                    (.NOT. present_12_excl_ei_list) .AND. (.NOT. present_12_excl_vdw_list)) THEN
     587              :                   list2 => list
     588              :                ELSE
     589              :                   ! Setup exclusion list for EI : always exclude itself
     590         1770 :                   dim0 = 1
     591              :                   ! exclude bond-neighbors (only if do_skip_12 .OR. do_skip_13 .OR. do_skip_14)
     592         1770 :                   dim1 = 0
     593              :                   IF (topology%exclude_ei == do_skip_12 .OR. &
     594         1770 :                       topology%exclude_ei == do_skip_13 .OR. &
     595         1326 :                       topology%exclude_ei == do_skip_14) dim1 = SIZE(ex_bond_list_ei(iatom)%array1)
     596         1770 :                   dim1 = dim1 + dim0
     597         1770 :                   dim2 = 0
     598         1770 :                   IF (topology%exclude_ei == do_skip_13 .OR. &
     599          864 :                       topology%exclude_ei == do_skip_14) dim2 = SIZE(ex_bend_list(iatom)%array1)
     600         1770 :                   dim2 = dim1 + dim2
     601         1770 :                   dim3 = 0
     602         1770 :                   IF (topology%exclude_ei == do_skip_14) dim3 = SIZE(ex_onfo_list(iatom)%array1)
     603         1770 :                   dim3 = dim2 + dim3
     604              : 
     605         1770 :                   IF (dim3 /= 0) THEN
     606         5310 :                      ALLOCATE (wlist(dim3))
     607         3540 :                      wlist(dim0:dim0) = iatom
     608         4098 :                      IF (dim1 > dim0) wlist(dim0 + 1:dim1) = ex_bond_list_ei(iatom)%array1
     609         4266 :                      IF (dim2 > dim1) wlist(dim1 + 1:dim2) = ex_bend_list(iatom)%array1
     610         2922 :                      IF (dim3 > dim2) wlist(dim2 + 1:dim3) = ex_onfo_list(iatom)%array1
     611              :                      ! Get a unique list
     612         7746 :                      DO i = 1, SIZE(wlist) - 1
     613         5976 :                         IF (wlist(i) == 0) CYCLE
     614        28896 :                         DO j = i + 1, SIZE(wlist)
     615        27126 :                            IF (wlist(j) == wlist(i)) wlist(j) = 0
     616              :                         END DO
     617              :                      END DO
     618         9516 :                      dim3 = SIZE(wlist) - COUNT(wlist == 0)
     619         5310 :                      ALLOCATE (list2(dim3))
     620         1770 :                      j = 0
     621         9516 :                      DO i = 1, SIZE(wlist)
     622         7746 :                         IF (wlist(i) == 0) CYCLE
     623         7746 :                         j = j + 1
     624         9516 :                         list2(j) = wlist(i)
     625              :                      END DO
     626         1770 :                      DEALLOCATE (wlist)
     627              :                      ! Unique list completed
     628              :                   END IF
     629              :                END IF
     630              :             END IF
     631       632826 :             exclusions(iatom)%list_exclude_vdw => list
     632       632826 :             exclusions(iatom)%list_exclude_ei => list2
     633              :             ! Keep a list of onfo atoms for proper selection of specialized 1-4
     634              :             ! potentials instead of conventional nonbonding potentials.
     635      1340767 :             ALLOCATE (exclusions(iatom)%list_onfo(SIZE(ex_onfo_list(iatom)%array1)))
     636              :             ! copy of data, not copy of pointer
     637      1253862 :             exclusions(iatom)%list_onfo = ex_onfo_list(iatom)%array1
     638       635310 :             IF (iw > 0) THEN
     639         1244 :                IF (ASSOCIATED(list)) &
     640         1244 :                   WRITE (iw, *) "exclusion list_vdw :: ", &
     641         1244 :                   "atom num :", iatom, "exclusion list ::", &
     642         6006 :                   list
     643         1244 :                IF (topology%exclude_vdw /= topology%exclude_ei) THEN
     644            9 :                   IF (ASSOCIATED(list2)) &
     645            9 :                      WRITE (iw, *) "exclusion list_ei :: ", &
     646            9 :                      "atom num :", iatom, "exclusion list ::", &
     647           35 :                      list2
     648              :                END IF
     649         1244 :                IF (ASSOCIATED(exclusions(iatom)%list_onfo)) &
     650         1244 :                   WRITE (iw, *) "onfo list :: ", &
     651         1244 :                   "atom num :", iatom, "onfo list ::", &
     652         3322 :                   exclusions(iatom)%list_onfo
     653              :             END IF
     654              :          END DO
     655              :          ! deallocate onfo
     656       635310 :          DO I = 1, natom
     657       635310 :             DEALLOCATE (ex_onfo_list(I)%array1)
     658              :          END DO
     659         2484 :          DEALLOCATE (ex_onfo_list)
     660              :          ! deallocate bends
     661       635310 :          DO I = 1, natom
     662       635310 :             DEALLOCATE (ex_bend_list(I)%array1)
     663              :          END DO
     664         2484 :          DEALLOCATE (ex_bend_list)
     665              :          ! deallocate bonds
     666         2484 :          IF (present_12_excl_ei_list) THEN
     667           40 :             DO I = 1, natom
     668           40 :                DEALLOCATE (ex_bond_list_ei(I)%array1)
     669              :             END DO
     670           10 :             DEALLOCATE (ex_bond_list_ei)
     671              :          ELSE
     672              :             NULLIFY (ex_bond_list_ei)
     673              :          END IF
     674         2484 :          IF (present_12_excl_vdw_list) THEN
     675           32 :             DO I = 1, natom
     676           32 :                DEALLOCATE (ex_bond_list_vdw(I)%array1)
     677              :             END DO
     678            8 :             DEALLOCATE (ex_bond_list_vdw)
     679              :          ELSE
     680              :             NULLIFY (ex_bond_list_vdw)
     681              :          END IF
     682       635310 :          DO I = 1, natom
     683       635310 :             DEALLOCATE (ex_bond_list(I)%array1)
     684              :          END DO
     685         9936 :          DEALLOCATE (ex_bond_list)
     686              :       END IF
     687        11404 :       CALL timestop(handle2)
     688              :       !-----------------------------------------------------------------------------
     689              :       !-----------------------------------------------------------------------------
     690              :       ! 11. Set the atomic_kind_set()%fist_potential%[qeff] (PART 1)
     691              :       !-----------------------------------------------------------------------------
     692        11404 :       CALL timeset(routineN//'_10', handle2)
     693        11404 :       CALL section_vals_val_get(force_env_section, "METHOD", i_val=method_name_id)
     694        11404 :       IF (method_name_id == do_fist) THEN
     695        13902 :          DO i = 1, SIZE(atomic_kind_set)
     696        11264 :             atomic_kind => atomic_kind_set(i)
     697        11264 :             CALL get_atomic_kind(atomic_kind=atomic_kind, name=atmname)
     698        11264 :             qeff = charge(i)
     699        11264 :             NULLIFY (fist_potential)
     700        11264 :             CALL allocate_potential(fist_potential)
     701        11264 :             CALL set_potential(potential=fist_potential, qeff=qeff)
     702        13902 :             CALL set_atomic_kind(atomic_kind=atomic_kind, fist_potential=fist_potential)
     703              :          END DO
     704              :       END IF
     705        11404 :       DEALLOCATE (charge)
     706        11404 :       CALL timestop(handle2)
     707              : 
     708              :       !-----------------------------------------------------------------------------
     709              :       !-----------------------------------------------------------------------------
     710              :       ! 12. Set the atom_list for molecule_kind in molecule_kind_set (PART 2)
     711              :       !-----------------------------------------------------------------------------
     712        11404 :       CALL timeset(routineN//'_11', handle2)
     713       157647 :       DO i = 1, SIZE(molecule_kind_set)
     714       146243 :          molecule_kind => molecule_kind_set(i)
     715              :          CALL get_molecule_kind(molecule_kind=molecule_kind, &
     716              :                                 natom=natom, molecule_list=molecule_list, &
     717       146243 :                                 atom_list=atom_list)
     718       146243 :          molecule => molecule_set(molecule_list(1))
     719              :          CALL get_molecule(molecule=molecule, &
     720       146243 :                            first_atom=first, last_atom=last)
     721       406199 :          DO j = 1, natom
     722     18853015 :             DO k = 1, SIZE(atomic_kind_set)
     723     18706772 :                atomic_kind => atomic_kind_set(k)
     724     18706772 :                CALL get_atomic_kind(atomic_kind=atomic_kind, name=atmname)
     725     18706772 :                IF (method_name_id == do_fist) THEN
     726     18366573 :                   CALL get_atomic_kind(atomic_kind=atomic_kind, fist_potential=fist_potential)
     727     18366573 :                   CALL get_potential(potential=fist_potential, qeff=qeff)
     728     18366573 :                   IF ((id2str(atom_list(j)%id_name) == atmname) .AND. (qeff == atom_info%atm_charge(first + j - 1))) THEN
     729       183239 :                      atom_list(j)%atomic_kind => atomic_kind_set(k)
     730     18549812 :                      EXIT
     731              :                   END IF
     732              :                ELSE
     733       340199 :                   IF (id2str(atom_list(j)%id_name) == atmname) THEN
     734        76717 :                      atom_list(j)%atomic_kind => atomic_kind_set(k)
     735       416916 :                      EXIT
     736              :                   END IF
     737              :                END IF
     738              :             END DO
     739              :          END DO
     740       303890 :          CALL set_molecule_kind(molecule_kind=molecule_kind, atom_list=atom_list)
     741              :       END DO
     742        11404 :       CALL timestop(handle2)
     743              : 
     744        11404 :       CALL timestop(handle)
     745              :       CALL cp_print_key_finished_output(iw, logger, subsys_section, &
     746        11404 :                                         "PRINT%TOPOLOGY_INFO/UTIL_INFO")
     747       136848 :    END SUBROUTINE topology_coordinate_pack
     748              : 
     749              : ! **************************************************************************************************
     750              : !> \brief Builds the exclusion list for VDW and EI if an explicit list of terms
     751              : !>        is provided by the user. Otherwise all possibilities are excluded
     752              : !> \param exclude_section ...
     753              : !> \param keyword ...
     754              : !> \param ex_bond_list ...
     755              : !> \param ex_bond_list_w ...
     756              : !> \param particle_set ...
     757              : !> \par History
     758              : !>      Teodoro Laino [tlaino] - 12.2009
     759              : ! **************************************************************************************************
     760           18 :    SUBROUTINE setup_exclusion_list(exclude_section, keyword, ex_bond_list, &
     761              :                                    ex_bond_list_w, particle_set)
     762              :       TYPE(section_vals_type), POINTER                   :: exclude_section
     763              :       CHARACTER(LEN=*), INTENT(IN)                       :: keyword
     764              :       TYPE(array1_list_type), DIMENSION(:), POINTER      :: ex_bond_list, ex_bond_list_w
     765              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     766              : 
     767              :       CHARACTER(LEN=default_string_length)               :: flag1, flag2
     768              :       CHARACTER(LEN=default_string_length), &
     769           18 :          DIMENSION(:), POINTER                           :: names
     770              :       INTEGER                                            :: i, ind, j, k, l, m, n_rep
     771              : 
     772            0 :       CPASSERT(ASSOCIATED(ex_bond_list))
     773           18 :       CPASSERT(ASSOCIATED(ex_bond_list_w))
     774           18 :       SELECT CASE (keyword)
     775              :       CASE ("BOND")
     776           18 :          CALL section_vals_val_get(exclude_section, keyword, n_rep_val=n_rep)
     777           72 :          DO j = 1, SIZE(ex_bond_list)
     778           54 :             CPASSERT(ASSOCIATED(ex_bond_list(j)%array1))
     779           54 :             CPASSERT(ASSOCIATED(ex_bond_list_w(j)%array1))
     780              : 
     781           54 :             flag1 = particle_set(j)%atomic_kind%name
     782           54 :             m = SIZE(ex_bond_list(j)%array1)
     783           54 :             CALL reallocate(ex_bond_list_w(j)%array1, 1, m)
     784              : 
     785           54 :             l = 0
     786          126 :             DO k = 1, m
     787           72 :                ind = ex_bond_list(j)%array1(k)
     788           72 :                flag2 = particle_set(ind)%atomic_kind%name
     789          150 :                DO i = 1, n_rep
     790              :                   CALL section_vals_val_get(exclude_section, keyword, i_rep_val=i, &
     791           24 :                                             c_vals=names)
     792           24 :                   IF (((TRIM(names(1)) == TRIM(flag1)) .AND. (TRIM(names(2)) == TRIM(flag2))) .OR. &
     793           72 :                       ((TRIM(names(1)) == TRIM(flag2)) .AND. (TRIM(names(2)) == TRIM(flag1)))) THEN
     794           24 :                      l = l + 1
     795           24 :                      ex_bond_list_w(j)%array1(l) = ind
     796              :                   END IF
     797              :                END DO
     798              :             END DO
     799           72 :             CALL reallocate(ex_bond_list_w(j)%array1, 1, l)
     800              :          END DO
     801              :       CASE DEFAULT
     802              :          CALL cp_abort(__LOCATION__, &
     803              :                        "<BOND> is supported as the <keyword> for "// &
     804              :                        "setup_exclusion_list, found unknown option "// &
     805           18 :                        "<"//TRIM(keyword)//">")
     806              :       END SELECT
     807              : 
     808           18 :    END SUBROUTINE setup_exclusion_list
     809              : 
     810              : END MODULE topology_coordinate_util
        

Generated by: LCOV version 2.0-1