63#include "./base/base_uses.f90" 
   67   CHARACTER(len=*), 
PARAMETER, 
PRIVATE :: moduleN = 
'topology_generate_util' 
   70   LOGICAL, 
PARAMETER                   :: debug_this_module = .false.
 
   96      INTEGER, 
INTENT(IN)                                :: natom, natom_prev, nbond_prev
 
   97      INTEGER, 
DIMENSION(:), 
INTENT(INOUT)               :: id_molname
 
   99      CHARACTER(LEN=default_string_length), 
PARAMETER    :: basename = 
"MOL" 
  101      CHARACTER(LEN=default_string_length)               :: molname
 
  102      INTEGER                                            :: i, id_undef, n, nmol
 
  109      ALLOCATE (atom_bond_list(natom))
 
  111         ALLOCATE (atom_bond_list(i)%array1(0))
 
  114      IF (
ASSOCIATED(conn_info%bond_a)) n = 
SIZE(conn_info%bond_a) - nbond_prev
 
  115      CALL reorder_structure(atom_bond_list, conn_info%bond_a(nbond_prev + 1:) - natom_prev, &
 
  116                             conn_info%bond_b(nbond_prev + 1:) - natom_prev, n)
 
  120      check = all(id_molname == id_undef) .OR. all(id_molname /= id_undef)
 
  123         IF (id_molname(i) == id_undef) 
THEN 
  125            CALL generate_molname_low(i, atom_bond_list, molname, id_molname)
 
  130         DEALLOCATE (atom_bond_list(i)%array1)
 
  132      DEALLOCATE (atom_bond_list)
 
 
  145   RECURSIVE SUBROUTINE generate_molname_low(i, atom_bond_list, molname, id_molname)
 
  146      INTEGER, 
INTENT(IN)                                :: i
 
  148      CHARACTER(LEN=default_string_length), 
INTENT(IN)   :: molname
 
  149      INTEGER, 
DIMENSION(:), 
INTENT(INOUT)               :: id_molname
 
  153      IF (debug_this_module) 
THEN 
  154         WRITE (*, *) 
"Entered with :", i
 
  155         WRITE (*, *) trim(molname)//
": entering with i:", i, 
" full series to test:: ", atom_bond_list(i)%array1
 
  156         IF ((trim(
id2str(id_molname(i))) /= 
"__UNDEF__") .AND. &
 
  157             (trim(
id2str(id_molname(i))) /= trim(molname))) 
THEN 
  158            WRITE (*, *) 
"Atom (", i, 
") has already a molecular name assigned ! ("//trim(
id2str(id_molname(i)))//
")." 
  159            WRITE (*, *) 
"New molecular name would be: ("//trim(molname)//
")." 
  160            WRITE (*, *) 
"Detecting something wrong in the molecular setup!" 
  164      id_molname(i) = 
str2id(molname)
 
  165      DO j = 1, 
SIZE(atom_bond_list(i)%array1)
 
  166         k = atom_bond_list(i)%array1(j)
 
  167         IF (debug_this_module) 
WRITE (*, *) 
"entering with i:", i, 
"testing :", k
 
  169         atom_bond_list(i)%array1(j) = -1
 
  170         WHERE (atom_bond_list(k)%array1 == i) atom_bond_list(k)%array1 = -1
 
  171         CALL generate_molname_low(k, atom_bond_list, molname, id_molname)
 
  173   END SUBROUTINE generate_molname_low
 
  184      LOGICAL, 
INTENT(in), 
OPTIONAL                      :: qmmm
 
  188      CHARACTER(len=*), 
PARAMETER :: routinen = 
'topology_generate_molecule' 
  189      INTEGER, 
PARAMETER                                 :: nblock = 100
 
  191      INTEGER :: atom_in_kind, atom_in_mol, first, handle, handle2, i, iatm, iatom, iend, ifirst, &
 
  192         ilast, inum, istart, itype, iw, j, jump1, jump2, last, max_mol_num, mol_num, mol_res, &
 
  193         mol_typ, myind, n, natom, nlocl, ntype, resid
 
  194      INTEGER, 
DIMENSION(:), 
POINTER                     :: qm_atom_index, wrk1, wrk2
 
  195      LOGICAL                                            :: do_again, found, my_qmmm
 
  204                                extension=
".subsysLog")
 
  205      CALL timeset(routinen, handle)
 
  206      NULLIFY (qm_atom_index)
 
  216      IF (
PRESENT(qmmm) .AND. 
PRESENT(qmmm_env)) my_qmmm = qmmm
 
  219      IF (
ASSOCIATED(atom_info%map_mol_typ)) 
DEALLOCATE (atom_info%map_mol_typ)
 
  220      ALLOCATE (atom_info%map_mol_typ(natom))
 
  222      IF (
ASSOCIATED(atom_info%map_mol_num)) 
DEALLOCATE (atom_info%map_mol_num)
 
  223      ALLOCATE (atom_info%map_mol_num(natom))
 
  225      IF (
ASSOCIATED(atom_info%map_mol_res)) 
DEALLOCATE (atom_info%map_mol_res)
 
  226      ALLOCATE (atom_info%map_mol_res(natom))
 
  229      atom_info%map_mol_typ(:) = 0
 
  230      atom_info%map_mol_num(:) = -1
 
  231      atom_info%map_mol_res(:) = 1
 
  235      atom_info%map_mol_typ(1) = 1
 
  238      wrk1(1) = atom_info%id_molname(1)
 
  243            atom_info%map_mol_typ(iatom) = ntype
 
  247            IF ((atom_info%id_molname(iatom) == atom_info%id_molname(iatom - 1)) .AND. &
 
  249               atom_info%map_mol_typ(iatom) = atom_info%map_mol_typ(iatom - 1)
 
  250               IF (atom_info%id_resname(iatom) == atom_info%id_resname(iatom - 1)) 
THEN 
  251                  atom_info%map_mol_res(iatom) = atom_info%map_mol_res(iatom - 1)
 
  254                  atom_info%map_mol_res(iatom) = resid
 
  260                  IF (atom_info%id_molname(iatom) == wrk1(itype)) 
THEN 
  261                     atom_info%map_mol_typ(iatom) = itype
 
  266               IF (.NOT. found) 
THEN 
  268                  atom_info%map_mol_typ(iatom) = ntype
 
  269                  IF (ntype > 
SIZE(wrk1)) 
CALL reallocate(wrk1, 1, 2*
SIZE(wrk1))
 
  270                  wrk1(ntype) = atom_info%id_molname(iatom)
 
  273               atom_info%map_mol_res(iatom) = resid
 
  276            IF (atom_info%id_molname(iatom - 1) == atom_info%id_molname(iatom)) 
THEN 
  277               atom_info%map_mol_typ(iatom) = ntype
 
  280               atom_info%map_mol_typ(iatom) = ntype
 
  286      IF (iw > 0) 
WRITE (iw, 
'(/,T2,A)') 
"Start of molecule generation" 
  290      ALLOCATE (atom_bond_list(natom))
 
  292         ALLOCATE (atom_bond_list(i)%array1(0))
 
  295      IF (
ASSOCIATED(conn_info%bond_a)) n = 
SIZE(conn_info%bond_a)
 
  297      CALL find_molecule(atom_bond_list, atom_info%map_mol_num, atom_info%id_molname)
 
  299         DEALLOCATE (atom_bond_list(i)%array1)
 
  301      DEALLOCATE (atom_bond_list)
 
  302      IF (iw > 0) 
WRITE (iw, 
'(/,T2,A)') 
"End of molecule generation" 
  305      IF (iw > 0) 
WRITE (iw, 
'(/,T2,A)') 
"Checking for non-continuous generated molecules" 
  307      ALLOCATE (wrk1(natom))
 
  308      ALLOCATE (wrk2(natom))
 
  309      wrk1 = atom_info%map_mol_num
 
  311      IF (debug_this_module) 
THEN 
  313            WRITE (*, 
'(2I10)') i, atom_info%map_mol_num(i)
 
  317      CALL sort(wrk1, natom, wrk2)
 
  319      mol_typ = wrk1(istart)
 
  321         IF (mol_typ /= wrk1(i)) 
THEN 
  323            first = minval(wrk2(istart:iend))
 
  324            last = maxval(wrk2(istart:iend))
 
  325            nlocl = last - first + 1
 
  326            IF (iend - istart + 1 /= nlocl) 
THEN 
  327               IF (debug_this_module) 
WRITE (*, *) iend, istart, iend - istart + 1, first, last, nlocl
 
  328               CALL cp_abort(__location__, &
 
  329                             "CP2K requires molecules to be contiguous and we have detected a non contiguous one!! "// &
 
  330                             "In particular a molecule defined from index ("//
cp_to_string(first)//
") to ("// &
 
  331                             cp_to_string(last)//
") contains other molecules, not connected! "// &
 
  332                             "Too late at this stage everything should be already ordered! "// &
 
  333                             "If you have not yet employed the REORDERING keyword, please do so. "// &
 
  334                             "It may help to fix this issue.")
 
  337            mol_typ = wrk1(istart)
 
  341      first = minval(wrk2(istart:iend))
 
  342      last = maxval(wrk2(istart:iend))
 
  343      nlocl = last - first + 1
 
  344      IF (iend - istart + 1 /= nlocl) 
THEN 
  345         IF (debug_this_module) 
WRITE (*, *) iend, istart, iend - istart + 1, first, last, nlocl
 
  346         CALL cp_abort(__location__, &
 
  347                       "CP2K requires molecules to be contiguous and we have detected a non contiguous one!! "// &
 
  348                       "In particular a molecule defined from index ("//
cp_to_string(first)//
") to ("// &
 
  349                       cp_to_string(last)//
") contains other molecules, not connected! "// &
 
  350                       "Too late at this stage everything should be already ordered! "// &
 
  351                       "If you have not yet employed the REORDERING keyword, please do so. "// &
 
  352                       "It may help to fix this issue.")
 
  356      IF (iw > 0) 
WRITE (iw, 
'(/,T2,A)') 
"End of check" 
  358      IF (iw > 0) 
WRITE (unit=iw, fmt=
"(/,T2,A)") 
"Start of renumbering molecules" 
  361         atom_info%map_mol_num(1) = 1
 
  363            IF (atom_info%id_molname(iatom) /= atom_info%id_molname(iatom - 1)) 
THEN 
  365            ELSE IF (atom_info%map_mol_res(iatom) /= atom_info%map_mol_res(iatom - 1)) 
THEN 
  366               mol_num = mol_num + 1
 
  368            atom_info%map_mol_num(iatom) = mol_num
 
  371         mol_typ = atom_info%map_mol_typ(1)
 
  372         mol_num = atom_info%map_mol_num(1)
 
  374            IF (atom_info%map_mol_typ(i) /= mol_typ) 
THEN 
  375               myind = atom_info%map_mol_num(i) - mol_num + 1
 
  376               cpassert(myind /= atom_info%map_mol_num(i - 1))
 
  377               mol_typ = atom_info%map_mol_typ(i)
 
  378               mol_num = atom_info%map_mol_num(i)
 
  380            atom_info%map_mol_num(i) = atom_info%map_mol_num(i) - mol_num + 1
 
  383      IF (iw > 0) 
WRITE (unit=iw, fmt=
"(/,T2,A)") 
"End of renumbering molecules" 
  386      CALL timeset(routinen//
"_PARA_RES", handle2)
 
  387      IF (iw > 0) 
WRITE (unit=iw, fmt=
"(/,T2,A,L2)") 
"Starting PARA_RES: ", 
topology%para_res
 
  390            atom_info%id_molname(:) = atom_info%id_resname(:)
 
  392            atom_info%map_mol_typ(1) = 1
 
  394            atom_info%map_mol_num(1) = 1
 
  396               IF (atom_info%id_molname(iatom) /= atom_info%id_molname(iatom - 1)) 
THEN 
  399               ELSE IF (atom_info%map_mol_res(iatom) /= atom_info%map_mol_res(iatom - 1)) 
THEN 
  400                  mol_num = mol_num + 1
 
  402               atom_info%map_mol_typ(iatom) = ntype
 
  403               atom_info%map_mol_num(iatom) = mol_num
 
  407            mol_typ = atom_info%map_mol_typ(1)
 
  408            mol_num = atom_info%map_mol_num(1)
 
  409            atom_info%map_mol_res(1) = mol_res
 
  411               IF ((atom_info%resid(i - 1) /= atom_info%resid(i)) .OR. &
 
  412                   (atom_info%id_resname(i - 1) /= atom_info%id_resname(i))) 
THEN 
  413                  mol_res = mol_res + 1
 
  415               IF ((atom_info%map_mol_typ(i) /= mol_typ) .OR. &
 
  416                   (atom_info%map_mol_num(i) /= mol_num)) 
THEN 
  417                  mol_typ = atom_info%map_mol_typ(i)
 
  418                  mol_num = atom_info%map_mol_num(i)
 
  421               atom_info%map_mol_res(i) = mol_res
 
  425      IF (iw > 0) 
WRITE (unit=iw, fmt=
"(/,T2,A)") 
"End of PARA_RES" 
  426      CALL timestop(handle2)
 
  430            WRITE (iw, 
'(4(1X,A,":",I0),2(1X,A,1X,A))') 
"iatom", iatom, &
 
  431               "map_mol_typ", atom_info%map_mol_typ(iatom), &
 
  432               "map_mol_num", atom_info%map_mol_num(iatom), &
 
  433               "map_mol_res", atom_info%map_mol_res(iatom), &
 
  434               "mol_name:", trim(
id2str(atom_info%id_molname(iatom))), &
 
  435               "res_name:", trim(
id2str(atom_info%id_resname(iatom)))
 
  441         IF (iw > 0) 
WRITE (iw, *) 
"MAP_MOL_NUM ", atom_info%map_mol_num
 
  442         IF (iw > 0) 
WRITE (iw, *) 
"MAP_MOL_TYP ", atom_info%map_mol_typ
 
  443         IF (iw > 0) 
WRITE (iw, *) 
"MAP_MOL_RES ", atom_info%map_mol_res
 
  444         ALLOCATE (qm_atom_index(
SIZE(qmmm_env%qm_atom_index)))
 
  445         qm_atom_index = qmmm_env%qm_atom_index
 
  446         cpassert(all(qm_atom_index /= 0))
 
  447         DO myind = 1, 
SIZE(qm_atom_index)
 
  448            IF (qm_atom_index(myind) == 0) cycle
 
  449            CALL find_boundary(atom_info%map_mol_typ, natom, ifirst, ilast, &
 
  450                               atom_info%map_mol_typ(qm_atom_index(myind)))
 
  451            CALL find_boundary(atom_info%map_mol_typ, atom_info%map_mol_num, natom, ifirst, ilast, &
 
  452                               atom_info%map_mol_typ(qm_atom_index(myind)), atom_info%map_mol_num(qm_atom_index(myind)))
 
  453            IF (iw > 0) 
WRITE (iw, *) 
"qm fragment:: ifirst, ilast", ifirst, ilast
 
  454            cpassert(((ifirst /= 0) .OR. (ilast /= natom)))
 
  455            DO iatm = ifirst, ilast
 
  456               atom_info%id_molname(iatm) = 
str2id(
s2s(
"_QM_"// &
 
  457                                                       trim(
id2str(atom_info%id_molname(iatm)))))
 
  458               IF (iw > 0) 
WRITE (iw, *) 
"QM Molecule name :: ", 
id2str(atom_info%id_molname(iatm))
 
  459               WHERE (qm_atom_index == iatm) qm_atom_index = 0
 
  461            DO iatm = 1, ifirst - 1
 
  462               IF (any(qm_atom_index == iatm)) do_again = .true.
 
  464            DO iatm = ilast + 1, natom
 
  465               IF (any(qm_atom_index == iatm)) do_again = .true.
 
  467            IF (iw > 0) 
WRITE (iw, *) 
" Another QM fragment? :: ", do_again
 
  468            IF (ifirst /= 1) 
THEN 
  469               jump1 = atom_info%map_mol_typ(ifirst) - atom_info%map_mol_typ(ifirst - 1)
 
  470               cpassert(jump1 <= 1 .AND. jump1 >= 0)
 
  471               jump1 = abs(jump1 - 1)
 
  475            IF (ilast /= natom) 
THEN 
  476               jump2 = atom_info%map_mol_typ(ilast + 1) - atom_info%map_mol_typ(ilast)
 
  477               cpassert(jump2 <= 1 .AND. jump2 >= 0)
 
  478               jump2 = abs(jump2 - 1)
 
  484            DO iatm = ifirst, natom
 
  485               atom_info%map_mol_typ(iatm) = atom_info%map_mol_typ(iatm) + jump1
 
  487            DO iatm = ilast + 1, natom
 
  488               atom_info%map_mol_typ(iatm) = atom_info%map_mol_typ(iatm) + jump2
 
  491               DO iatm = ifirst, ilast
 
  492                  atom_info%map_mol_num(iatm) = 1
 
  497               CALL find_boundary(atom_info%map_mol_typ, natom, first, last, atom_info%map_mol_typ(ilast + 1))
 
  498               CALL find_boundary(atom_info%map_mol_typ, atom_info%map_mol_num, natom, ifirst, ilast, &
 
  499                                  atom_info%map_mol_typ(ilast + 1), atom_info%map_mol_num(ilast + 1))
 
  500               atom_in_mol = ilast - ifirst + 1
 
  502               DO iatm = first, last, atom_in_mol
 
  503                  atom_info%map_mol_num(iatm:iatm + atom_in_mol - 1) = inum
 
  508            IF (.NOT. do_again) 
EXIT 
  510         DEALLOCATE (qm_atom_index)
 
  513            WRITE (iw, *) 
"After the QM/MM Setup:" 
  515               WRITE (iw, *) 
"      iatom,map_mol_typ,map_mol_num ", iatom, &
 
  516                  atom_info%map_mol_typ(iatom), atom_info%map_mol_num(iatom)
 
  524         WRITE (iw, *) 
"SUMMARY:: Number of molecule kinds found:", ntype
 
  525         ntype = maxval(atom_info%map_mol_typ)
 
  527            atom_in_kind = count(atom_info%map_mol_typ == i)
 
  528            WRITE (iw, *) 
"Molecule kind:", i, 
" contains", atom_in_kind, 
" atoms" 
  529            IF (atom_in_kind <= 1) cycle
 
  530            CALL find_boundary(atom_info%map_mol_typ, natom, first, last, i)
 
  531            WRITE (iw, *) 
"Boundary atoms:", first, last
 
  532            cpassert(last - first + 1 == atom_in_kind)
 
  533            max_mol_num = maxval(atom_info%map_mol_num(first:last))
 
  534            WRITE (iw, *) 
"Number of molecules of kind", i, 
"is ::", max_mol_num
 
  535            atom_in_mol = atom_in_kind/max_mol_num
 
  536            WRITE (iw, *) 
"Number of atoms per each molecule:", atom_in_mol
 
  537            WRITE (iw, *) 
"MAP_MOL_TYP::", atom_info%map_mol_typ(first:last)
 
  538            WRITE (iw, *) 
"MAP_MOL_NUM::", atom_info%map_mol_num(first:last)
 
  539            WRITE (iw, *) 
"MAP_MOL_RES::", atom_info%map_mol_res(first:last)
 
  541            DO j = 1, max_mol_num
 
  542               IF (count(atom_info%map_mol_num(first:last) == j) /= atom_in_mol) 
THEN 
  543                  WRITE (iw, *) 
"molecule type:", i, 
"molecule num:", j, 
" has ", &
 
  544                     count(atom_info%map_mol_num(first:last) == j), &
 
  545                     " atoms instead of ", atom_in_mol, 
" ." 
  546                  CALL cp_abort(__location__, &
 
  547                                "Two molecules of the same kind have "// &
 
  548                                "been created with different numbers of atoms!")
 
  554                                        "PRINT%TOPOLOGY_INFO/UTIL_INFO")
 
  555      CALL timestop(handle)
 
 
  570      CHARACTER(len=*), 
PARAMETER :: routinen = 
'topology_generate_bond' 
  572      CHARACTER(LEN=2)                                   :: upper_sym_1
 
  573      INTEGER :: cbond, handle, handle2, i, iatm1, iatm2, iatom, ibond, idim, iw, j, jatom, k, &
 
  574         n_bonds, n_heavy_bonds, n_hydr_bonds, n_rep, natom, npairs, output_unit
 
  575      INTEGER, 
ALLOCATABLE, 
DIMENSION(:)                 :: bond_a, bond_b, 
list, map_nb
 
  576      INTEGER, 
DIMENSION(:), 
POINTER                     :: isolated_atoms, tmp_v
 
  577      LOGICAL                                            :: connectivity_ok, explicit, print_info
 
  578      LOGICAL, 
ALLOCATABLE, 
DIMENSION(:)                 :: h_list
 
  579      REAL(kind=
dp)                                      :: bondparm_factor, cell_v(3), dr(3), &
 
  580                                                            ksign, my_maxrad, r2, r2_min, rbond, &
 
  582      REAL(kind=
dp), 
DIMENSION(1, 1)                     :: r_max, r_minsq
 
  583      REAL(kind=
dp), 
DIMENSION(:), 
POINTER               :: radius
 
  584      REAL(kind=
dp), 
DIMENSION(:, :), 
POINTER            :: pbc_coord
 
  596      NULLIFY (logger, particle_set, atomic_kind_set, nonbonded, bond_section, generate_section)
 
  597      NULLIFY (isolated_atoms, tmp_v)
 
  598      CALL timeset(routinen, handle)
 
  602                                extension=
".subsysLog")
 
  604      ALLOCATE (isolated_atoms(0))
 
  612            CALL reallocate(isolated_atoms, 1, 
SIZE(isolated_atoms) + 
SIZE(tmp_v))
 
  613            isolated_atoms(
SIZE(isolated_atoms) - 
SIZE(tmp_v) + 1:
SIZE(isolated_atoms)) = tmp_v
 
  618      bondparm_factor = 
topology%bondparm_factor
 
  623      ALLOCATE (radius(natom))
 
  624      ALLOCATE (
list(natom))
 
  625      ALLOCATE (h_list(natom))
 
  626      ALLOCATE (pbc_coord(3, natom))
 
  628      CALL timeset(trim(routinen)//
"_1", handle2)
 
  631         upper_sym_1 = trim(
id2str(atom_info%id_element(iatom)))
 
  633            CALL get_ptable_info(symbol=upper_sym_1, covalent_radius=radius(iatom))
 
  637            cpabort(
"Illegal bondparm_type")
 
  639         IF (upper_sym_1 == 
"H ") h_list(iatom) = .true.
 
  641         IF (any(isolated_atoms == iatom)) radius(iatom) = 0.0_dp
 
  643         IF (iw > 0) 
WRITE (iw, 
'(T2,"GENERATE|",5X,A,T50,A5,T60,A,T69,F12.6)') &
 
  644            "In topology_generate_bond :: iatom = ", upper_sym_1, &
 
  645            "radius:", radius(iatom)
 
  647      CALL timestop(handle2)
 
  648      CALL timeset(trim(routinen)//
"_2", handle2)
 
  651      ALLOCATE (atomic_kind_set(1))
 
  654      my_maxrad = maxval(radius)*2.0_dp
 
  655      atomic_kind => atomic_kind_set(1)
 
  657                           name=
"XXX", element_symbol=
"XXX", mass=0.0_dp, atom_list=
list)
 
  660      IF (my_maxrad*bondparm_factor > r_max(1, 1) .AND. (.NOT. 
topology%molname_generated)) 
THEN 
  661         IF (output_unit > 0) 
THEN 
  662            WRITE (output_unit, 
'(T2,"GENERATE|",A)') &
 
  663               " ERROR in connectivity generation!", &
 
  664               " The THRESHOLD to select possible bonds is larger than the max. bondlength", &
 
  665               " used to build the neighbors lists. Increase the BONDLENGTH_MAX parameter" 
  666            WRITE (output_unit, 
'(T2,"GENERATE|",2(A,F11.6),A)') &
 
  667               " Present THRESHOLD (", my_maxrad*bondparm_factor, 
" )."// &
 
  668               " Present BONDLENGTH_MAX (", r_max(1, 1), 
" )" 
  673         particle_set(i)%atomic_kind => atomic_kind_set(1)
 
  674         particle_set(i)%r(1) = atom_info%r(1, i)
 
  675         particle_set(i)%r(2) = atom_info%r(2, i)
 
  676         particle_set(i)%r(3) = atom_info%r(3, i)
 
  677         pbc_coord(:, i) = 
pbc(atom_info%r(:, i), 
topology%cell)
 
  681      CALL timestop(handle2)
 
  682      CALL timeset(trim(routinen)//
"_3", handle2)
 
  684                                     cell=
topology%cell, r_max=r_max, r_minsq=r_minsq, &
 
  685                                     ei_scale14=1.0_dp, vdw_scale14=1.0_dp, nonbonded=nonbonded, &
 
  686                                     para_env=para_env, build_from_scratch=.true., geo_check=.true., &
 
  687                                     mm_section=generate_section)
 
  689         WRITE (iw, 
'(T2,"GENERATE| Number of prescreened bonds (neighbors):",T71,I10)') &
 
  690            nonbonded%neighbor_kind_pairs(1)%npairs
 
  693      DO i = 1, 
SIZE(nonbonded%neighbor_kind_pairs)
 
  694         npairs = npairs + nonbonded%neighbor_kind_pairs(i)%npairs
 
  696      ALLOCATE (bond_a(npairs))
 
  697      ALLOCATE (bond_b(npairs))
 
  698      ALLOCATE (map_nb(npairs))
 
  700      DO j = 1, 
SIZE(nonbonded%neighbor_kind_pairs)
 
  701         DO i = 1, nonbonded%neighbor_kind_pairs(j)%npairs
 
  703            bond_a(idim) = nonbonded%neighbor_kind_pairs(j)%list(1, i)
 
  704            bond_b(idim) = nonbonded%neighbor_kind_pairs(j)%list(2, i)
 
  708      CALL timestop(handle2)
 
  709      CALL timeset(trim(routinen)//
"_4", handle2)
 
  711      ALLOCATE (bond_list(natom))
 
  713         ALLOCATE (bond_list(i)%array1(0))
 
  714         ALLOCATE (bond_list(i)%array2(0))
 
  725      connectivity_ok = .false.
 
  729         atom_info%id_molname = 
str2id(
s2s(
"TO_DEFINE_LATER"))
 
  735      DO WHILE (.NOT. connectivity_ok)
 
  739            IF (h_list(iatm1)) cycle
 
  740            DO j = 1, 
SIZE(bond_list(iatm1)%array1)
 
  741               iatm2 = bond_list(iatm1)%array1(j)
 
  742               IF (atom_info%id_molname(iatm1) /= atom_info%id_molname(iatm2)) cycle
 
  743               IF (h_list(iatm2) .OR. (iatm2 <= iatm1)) cycle
 
  744               k = bond_list(iatm1)%array2(j)
 
  745               ksign = sign(1.0_dp, real(k, kind=
dp))
 
  747               cell_v = matmul(
topology%cell%hmat, &
 
  748                               REAL(nonbonded%neighbor_kind_pairs(k)%cell_vector, kind=
dp))
 
  749               dr = pbc_coord(:, iatm1) - pbc_coord(:, iatm2) - ksign*cell_v
 
  750               r2 = dot_product(dr, dr)
 
  751               IF (r2 <= r_minsq(1, 1)) 
THEN 
  752                  CALL cp_abort(__location__, &
 
  753                                "bond distance between atoms less then the smallest distance provided "// &
 
  757               IF ((any(isolated_atoms == iatm1)) .OR. (any(isolated_atoms == iatm2))) cycle
 
  761                  rbond = radius(iatm1) + radius(iatm2)
 
  763                  rbond = max(radius(iatm1), radius(iatm2))
 
  766               rbond2 = rbond2*(bondparm_factor)**2
 
  768               IF (r2 <= rbond2) 
THEN 
  769                  n_heavy_bonds = n_heavy_bonds + 1
 
  770                  CALL add_bonds_list(conn_info, iatm1, iatm2, n_heavy_bonds)
 
  775         n_bonds = n_heavy_bonds
 
  778         IF (output_unit > 0) 
WRITE (output_unit, *)
 
  780            IF (.NOT. h_list(iatm1)) cycle
 
  781            r2_min = huge(0.0_dp)
 
  784            DO j = 1, 
SIZE(bond_list(iatm1)%array1)
 
  785               iatm2 = bond_list(iatm1)%array1(j)
 
  787               IF (atom_info%id_molname(iatm1) /= atom_info%id_molname(iatm2)) cycle
 
  788               IF (h_list(iatm2) .AND. (iatm2 <= iatm1)) cycle
 
  790               IF ((any(isolated_atoms == iatm1)) .OR. (any(isolated_atoms == iatm2))) cycle
 
  792               k = bond_list(iatm1)%array2(j)
 
  793               ksign = sign(1.0_dp, real(k, kind=
dp))
 
  795               cell_v = matmul(
topology%cell%hmat, &
 
  796                               REAL(nonbonded%neighbor_kind_pairs(k)%cell_vector, kind=
dp))
 
  797               dr = pbc_coord(:, iatm1) - pbc_coord(:, iatm2) - ksign*cell_v
 
  798               r2 = dot_product(dr, dr)
 
  799               IF (r2 <= r_minsq(1, 1)) 
THEN 
  800                  CALL cp_abort(__location__, &
 
  801                                "bond distance between atoms less then the smallest distance provided "// &
 
  804               IF (r2 <= r2_min) 
THEN 
  809            IF (ibond == -1) 
THEN 
  810               IF (output_unit > 0 .AND. print_info) 
THEN 
  811                  WRITE (output_unit, 
'(T2,"GENERATE|",1X,A,I10,A)') &
 
  812                     "WARNING:: No connections detected for Hydrogen - Atom Nr:", iatm1, 
" !" 
  815               n_hydr_bonds = n_hydr_bonds + 1
 
  816               n_bonds = n_bonds + 1
 
  817               CALL add_bonds_list(conn_info, min(iatm1, ibond), max(iatm1, ibond), n_bonds)
 
  820         IF (output_unit > 0) 
THEN 
  821            WRITE (output_unit, 
'(T2,"GENERATE|",1X,A,T71,I10)') &
 
  822               " Preliminary Number of Bonds generated:", n_bonds
 
  826         CALL connectivity_external_control(section=bond_section, &
 
  827                                            iarray1=conn_info%bond_a, &
 
  828                                            iarray2=conn_info%bond_b, &
 
  831                                            output_unit=output_unit)
 
  838            IF (.NOT. 
topology%reorder_atom) 
THEN 
  840               IF (output_unit > 0) 
WRITE (output_unit, 
'(T2,"GENERATE|",A)') &
 
  841                  " Molecules names have been generated. Now reordering particle set in order to have ", &
 
  842                  " atoms belonging to the same molecule in a sequential order." 
  844            connectivity_ok = .true.
 
  847            connectivity_ok = check_generate_mol(conn_info%bond_a, conn_info%bond_b, &
 
  848                                                 atom_info, bondparm_factor, output_unit)
 
  850         IF (my_maxrad*bondparm_factor > r_max(1, 1) .AND. (.NOT. 
topology%molname_generated)) 
THEN 
  851            IF (output_unit > 0) 
THEN 
  852               WRITE (output_unit, 
'(T2,"GENERATE|",A)') &
 
  853                  " ERROR in connectivity generation!", &
 
  854                  " The THRESHOLD to select possible bonds is bigger than the MAX bondlength", &
 
  855                  " used to build the neighbors lists. Increase the BONDLENGTH_MAX patameter" 
  856               WRITE (output_unit, 
'(T2,"GENERATE|",2(A,F11.6),A)') &
 
  857                  " Present THRESHOLD (", my_maxrad*bondparm_factor, 
" )."// &
 
  858                  " Present BONDLENGTH_MAX (", r_max(1, 1), 
" )" 
  863      IF (connectivity_ok .AND. (output_unit > 0)) 
THEN 
  864         WRITE (output_unit, 
'(T2,"GENERATE|",A)') &
 
  865            "  Achieved consistency in connectivity generation." 
  868      CALL timestop(handle2)
 
  869      CALL timeset(trim(routinen)//
"_6", handle2)
 
  872         DEALLOCATE (bond_list(i)%array1)
 
  873         DEALLOCATE (bond_list(i)%array2)
 
  875      DEALLOCATE (bond_list)
 
  876      DEALLOCATE (pbc_coord)
 
  882      CALL timestop(handle2)
 
  883      IF (output_unit > 0 .AND. n_bonds > 0) 
THEN 
  884         WRITE (output_unit, 
'(T2,"GENERATE|",1X,A,T71,I10)') 
" Number of Bonds generated:", &
 
  887      CALL timeset(trim(routinen)//
"_7", handle2)
 
  892         DO ibond = 1, 
SIZE(conn_info%bond_a)
 
  893            iatom = conn_info%bond_a(ibond)
 
  894            jatom = conn_info%bond_b(ibond)
 
  895            IF ((atom_info%id_molname(iatom) /= atom_info%id_molname(jatom)) .OR. &
 
  896                (atom_info%resid(iatom) /= atom_info%resid(jatom)) .OR. &
 
  897                (atom_info%id_resname(iatom) /= atom_info%id_resname(jatom))) 
THEN 
  898               IF (iw > 0) 
WRITE (iw, *) 
"      PARA_RES, bond between molecules atom ", &
 
  903               conn_info%c_bond_a(cbond) = iatom
 
  904               conn_info%c_bond_b(cbond) = jatom
 
  906               IF (atom_info%id_molname(iatom) /= atom_info%id_molname(jatom)) 
THEN 
  907                  cpabort(
"Bonds between different molecule types?")
 
  912      CALL timestop(handle2)
 
  913      DEALLOCATE (isolated_atoms)
 
  914      CALL timestop(handle)
 
  916                                        "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
 
 
  929   FUNCTION check_generate_mol(bond_a, bond_b, atom_info, bondparm_factor, output_unit) &
 
  931      INTEGER, 
DIMENSION(:), 
POINTER                     :: bond_a, bond_b
 
  933      REAL(kind=
dp), 
INTENT(INOUT)                       :: bondparm_factor
 
  934      INTEGER, 
INTENT(IN)                                :: output_unit
 
  937      CHARACTER(len=*), 
PARAMETER :: routinen = 
'check_generate_mol' 
  939      CHARACTER(LEN=10)                                  :: ctmp1, ctmp2, ctmp3
 
  940      INTEGER                                            :: handle, i, idim, itype, j, mol_natom, &
 
  942      INTEGER, 
ALLOCATABLE, 
DIMENSION(:, :)              :: mol_info_tmp
 
  943      INTEGER, 
DIMENSION(:), 
POINTER                     :: mol_map, mol_map_o, wrk
 
  944      INTEGER, 
DIMENSION(:, :), 
POINTER                  :: mol_info
 
  945      LOGICAL, 
DIMENSION(:), 
POINTER                     :: icheck
 
  948      CALL timeset(routinen, handle)
 
  950      natom = 
SIZE(atom_info%id_atmname)
 
  951      ALLOCATE (bond_list(natom))
 
  953         ALLOCATE (bond_list(i)%array1(0))
 
  956      ALLOCATE (mol_map(natom))
 
  957      ALLOCATE (mol_map_o(natom))
 
  958      ALLOCATE (wrk(natom))
 
  961         mol_map(i) = atom_info%id_molname(i)
 
  965      CALL sort(mol_map, natom, wrk)
 
  979      ALLOCATE (mol_info_tmp(natom, 2))
 
  984      mol_info_tmp(1, 1) = itype
 
  986         IF (mol_map(i) /= itype) 
THEN 
  989            mol_info_tmp(nsize, 1) = itype
 
  990            mol_info_tmp(nsize - 1, 2) = idim
 
  996      mol_info_tmp(nsize, 2) = idim
 
  998      ALLOCATE (mol_info(nsize, 4))
 
  999      mol_info(1:nsize, 1:2) = mol_info_tmp(1:nsize, 1:2)
 
 1000      DEALLOCATE (mol_info_tmp)
 
 1007      ALLOCATE (icheck(natom))
 
 1010         IF (icheck(i)) cycle
 
 1011         itype = mol_map_o(i)
 
 1014         DO j = 1, 
SIZE(mol_info)
 
 1015            IF (itype == mol_info(j, 1)) 
EXIT 
 1017         mol_info(j, 3) = mol_info(j, 3) + 1
 
 1018         IF (mol_info(j, 4) == 0) mol_info(j, 4) = mol_natom
 
 1019         IF (mol_info(j, 4) /= mol_natom) 
THEN 
 1025            bondparm_factor = bondparm_factor*1.05_dp
 
 1026            IF (output_unit < 0) 
EXIT 
 1027            WRITE (output_unit, 
'(/,T2,"GENERATE|",A)') 
" WARNING in connectivity generation!" 
 1028            WRITE (output_unit, 
'(T2,"GENERATE|",A)') &
 
 1029               ' Two molecules/residues named ('//trim(
id2str(itype))//
') have different '// &
 
 1034            WRITE (output_unit, 
'(T2,"GENERATE|",A)') 
' Molecule starting at position ('// &
 
 1035               trim(ctmp1)//
') has Nr. <'//trim(ctmp2)// &
 
 1036               '> of atoms.', 
' while the other same molecules have Nr. <'// &
 
 1037               trim(ctmp3)//
'> of atoms!' 
 1038            WRITE (output_unit, 
'(T2,"GENERATE|",A)') &
 
 1039               ' Increasing bondparm_factor by 1.05.. An error was found in the generated', &
 
 1040               ' connectivity. Retry...' 
 1041            WRITE (output_unit, 
'(T2,"GENERATE|",A,F11.6,A,/)') &
 
 1042               " Present value of BONDPARM_FACTOR (", bondparm_factor, 
" )." 
 1048      DEALLOCATE (mol_info)
 
 1049      DEALLOCATE (mol_map)
 
 1050      DEALLOCATE (mol_map_o)
 
 1053         DEALLOCATE (bond_list(i)%array1)
 
 1055      DEALLOCATE (bond_list)
 
 1056      CALL timestop(handle)
 
 1057   END FUNCTION check_generate_mol
 
 1073   SUBROUTINE connectivity_external_control(section, Iarray1, Iarray2, Iarray3, Iarray4, nvar, &
 
 1074                                            topology, output_unit, is_impr)
 
 1076      INTEGER, 
DIMENSION(:), 
POINTER                     :: iarray1, iarray2
 
 1077      INTEGER, 
DIMENSION(:), 
OPTIONAL, 
POINTER           :: iarray3, iarray4
 
 1078      INTEGER, 
INTENT(INOUT)                             :: nvar
 
 1080      INTEGER, 
INTENT(IN)                                :: output_unit
 
 1081      LOGICAL, 
INTENT(IN), 
OPTIONAL                      :: is_impr
 
 1083      CHARACTER(LEN=8)                                   :: fmt
 
 1084      INTEGER                                            :: do_action, do_it, i, j, k, n_rep, &
 
 1085                                                            n_rep_val, natom, new_size, nsize
 
 1086      INTEGER, 
DIMENSION(:), 
POINTER                     :: atlist, ilist1, ilist2, ilist3, ilist4
 
 1087      LOGICAL                                            :: explicit, ip3, ip4
 
 1091      ip3 = 
PRESENT(iarray3)
 
 1092      ip4 = 
PRESENT(iarray4)
 
 1094      IF (ip3) nsize = nsize + 1
 
 1095      IF (ip3 .AND. ip4) nsize = nsize + 1
 
 1101         NULLIFY (ilist1, ilist2, ilist3, ilist4, atlist)
 
 1102         ALLOCATE (ilist1(nvar))
 
 1103         ALLOCATE (ilist2(nvar))
 
 1104         ilist1 = iarray1(1:nvar)
 
 1105         ilist2 = iarray2(1:nvar)
 
 1109            ALLOCATE (ilist3(nvar))
 
 1110            ilist3 = iarray3(1:nvar)
 
 1112            ALLOCATE (ilist3(nvar))
 
 1113            ALLOCATE (ilist4(nvar))
 
 1114            ilist3 = iarray3(1:nvar)
 
 1115            ilist4 = iarray4(1:nvar)
 
 1120         CALL list_canonical_order(ilist1, ilist2, ilist3, ilist4, nsize, is_impr)
 
 1130               cpassert(
SIZE(atlist) == nsize)
 
 1132               CALL check_element_list(do_it, do_action, atlist, ilist1, ilist2, ilist3, ilist4, &
 
 1134               IF (do_action == 
do_add) 
THEN 
 1138                     IF (output_unit > 0) 
THEN 
 1139                        WRITE (output_unit, 
'(T2,"ADD|",1X,A,I6,'//trim(fmt)//
'(A,I6),A,T64,A,I6)') &
 
 1141                           atlist(1), (
",", atlist(k), k=2, nsize), 
") added.", 
" NEW size::", nvar
 
 1143                     IF (nvar > 
SIZE(iarray1)) 
THEN 
 1144                        new_size = int(5 + 1.2*nvar)
 
 1156                     iarray1(do_it + 1:nvar) = iarray1(do_it:nvar - 1)
 
 1157                     iarray2(do_it + 1:nvar) = iarray2(do_it:nvar - 1)
 
 1158                     iarray1(do_it) = ilist1(do_it)
 
 1159                     iarray2(do_it) = ilist2(do_it)
 
 1162                        iarray3(do_it + 1:nvar) = iarray3(do_it:nvar - 1)
 
 1163                        iarray3(do_it) = ilist3(do_it)
 
 1165                        iarray3(do_it + 1:nvar) = iarray3(do_it:nvar - 1)
 
 1166                        iarray4(do_it + 1:nvar) = iarray4(do_it:nvar - 1)
 
 1167                        iarray3(do_it) = ilist3(do_it)
 
 1168                        iarray4(do_it) = ilist4(do_it)
 
 1171                     IF (output_unit > 0) 
THEN 
 1172                        WRITE (output_unit, 
'(T2,"ADD|",1X,A,I6,'//trim(fmt)//
'(A,I6),A,T80,A)') &
 
 1174                           atlist(1), (
",", atlist(k), k=2, nsize), 
") already found.", 
"X" 
 1181                     IF (output_unit > 0) 
THEN 
 1182                        WRITE (output_unit, 
'(T2,"RMV|",1X,A,I6,'//trim(fmt)//
'(A,I6),A,T64,A,I6)') &
 
 1184                           atlist(1), (
",", atlist(k), k=2, nsize), 
") removed.", 
" NEW size::", nvar
 
 1186                     iarray1(do_it:nvar) = iarray1(do_it + 1:nvar + 1)
 
 1187                     iarray2(do_it:nvar) = iarray2(do_it + 1:nvar + 1)
 
 1188                     iarray1(nvar + 1) = -huge(0)
 
 1189                     iarray2(nvar + 1) = -huge(0)
 
 1192                        iarray3(do_it:nvar) = iarray3(do_it + 1:nvar + 1)
 
 1193                        iarray3(nvar + 1) = -huge(0)
 
 1195                        iarray3(do_it:nvar) = iarray3(do_it + 1:nvar + 1)
 
 1196                        iarray4(do_it:nvar) = iarray4(do_it + 1:nvar + 1)
 
 1197                        iarray3(nvar + 1) = -huge(0)
 
 1198                        iarray4(nvar + 1) = -huge(0)
 
 1201                     IF (output_unit > 0) 
THEN 
 1202                        WRITE (output_unit, 
'(T2,"RMV|",1X,A,I6,'//trim(fmt)//
'(A,I6),A,T80,A)') &
 
 1204                           atlist(1), (
",", atlist(k), k=2, nsize), 
") not found.", 
"X" 
 1225   END SUBROUTINE connectivity_external_control
 
 1238   SUBROUTINE list_canonical_order(Ilist1, Ilist2, Ilist3, Ilist4, nsize, is_impr)
 
 1239      INTEGER, 
DIMENSION(:), 
POINTER                     :: ilist1, ilist2
 
 1240      INTEGER, 
DIMENSION(:), 
OPTIONAL, 
POINTER           :: ilist3, ilist4
 
 1241      INTEGER, 
INTENT(IN)                                :: nsize
 
 1242      LOGICAL, 
INTENT(IN), 
OPTIONAL                      :: is_impr
 
 1244      INTEGER                                            :: i, ss(3), tmp1, tmp2, tmp3, tt(3)
 
 1248      IF (
PRESENT(is_impr)) do_impr = is_impr
 
 1251         DO i = 1, 
SIZE(ilist1)
 
 1254            ilist1(i) = min(tmp1, tmp2)
 
 1255            ilist2(i) = max(tmp1, tmp2)
 
 1258         DO i = 1, 
SIZE(ilist1)
 
 1261            ilist1(i) = min(tmp1, tmp2)
 
 1262            ilist3(i) = max(tmp1, tmp2)
 
 1265         DO i = 1, 
SIZE(ilist1)
 
 1266            IF (.NOT. do_impr) 
THEN 
 1269               ilist1(i) = min(tmp1, tmp2)
 
 1270               IF (ilist1(i) == tmp2) 
THEN 
 1272                  ilist3(i) = ilist2(i)
 
 1275               ilist4(i) = max(tmp1, tmp2)
 
 1280               CALL sort(tt, 3, ss)
 
 1288   END SUBROUTINE list_canonical_order
 
 1302   SUBROUTINE check_element_list(do_it, do_action, atlist, Ilist1, Ilist2, Ilist3, Ilist4, &
 
 1304      INTEGER, 
INTENT(OUT)                               :: do_it
 
 1305      INTEGER, 
INTENT(IN)                                :: do_action
 
 1306      INTEGER, 
DIMENSION(:), 
POINTER                     :: atlist, ilist1, ilist2
 
 1307      INTEGER, 
DIMENSION(:), 
OPTIONAL, 
POINTER           :: ilist3, ilist4
 
 1308      LOGICAL, 
INTENT(IN), 
OPTIONAL                      :: is_impr
 
 1310      INTEGER                                            :: i, iend, istart, ndim, new_size, nsize, &
 
 1311                                                            ss(3), tmp1, tmp2, tmp3, tt(3)
 
 1312      INTEGER, 
DIMENSION(4)                              :: tmp
 
 1313      LOGICAL                                            :: do_impr, found
 
 1316      IF (
PRESENT(is_impr)) do_impr = is_impr
 
 1318      nsize = 
SIZE(atlist)
 
 1327         tmp(1) = min(tmp1, tmp2)
 
 1328         tmp(2) = max(tmp1, tmp2)
 
 1332         tmp(1) = min(tmp1, tmp2)
 
 1333         tmp(3) = max(tmp1, tmp2)
 
 1335         IF (.NOT. do_impr) 
THEN 
 1338            tmp(1) = min(tmp1, tmp2)
 
 1339            IF (tmp(1) == tmp2) 
THEN 
 1344            tmp(4) = max(tmp1, tmp2)
 
 1349            CALL sort(tt, 3, ss)
 
 1357         IF (ilist1(istart) >= tmp(1)) 
EXIT 
 1360      IF (istart <= ndim) 
THEN 
 1361         IF (ilist1(istart) > tmp(1) .AND. (istart /= 1)) istart = istart - 1
 
 1363      DO iend = istart, ndim
 
 1364         IF (ilist1(iend) /= tmp(1)) 
EXIT 
 1366      IF (iend == ndim + 1) iend = ndim
 
 1371            IF ((ilist1(i) > tmp(1)) .OR. (ilist2(i) > tmp(2))) 
EXIT 
 1372            IF ((ilist1(i) == tmp(1)) .AND. (ilist2(i) == tmp(2))) 
THEN 
 1379            IF ((ilist1(i) > tmp(1)) .OR. (ilist2(i) > tmp(2)) .OR. (ilist3(i) > tmp(3))) 
EXIT 
 1380            IF ((ilist1(i) == tmp(1)) .AND. (ilist2(i) == tmp(2)) .AND. (ilist3(i) == tmp(3))) 
THEN 
 1387            IF ((ilist1(i) > tmp(1)) .OR. (ilist2(i) > tmp(2)) .OR. (ilist3(i) > tmp(3)) .OR. (ilist4(i) > tmp(4))) 
EXIT 
 1388            IF ((ilist1(i) == tmp(1)) .AND. (ilist2(i) == tmp(2)) &
 
 1389                .AND. (ilist3(i) == tmp(3)) .AND. (ilist4(i) == tmp(4))) 
THEN 
 1395      SELECT CASE (do_action)
 
 1412            ilist1(i + 1:new_size) = ilist1(i:ndim)
 
 1413            ilist2(i + 1:new_size) = ilist2(i:ndim)
 
 1419               ilist3(i + 1:new_size) = ilist3(i:ndim)
 
 1424               ilist3(i + 1:new_size) = ilist3(i:ndim)
 
 1425               ilist4(i + 1:new_size) = ilist4(i:ndim)
 
 1435            ilist1(i:new_size) = ilist1(i + 1:ndim)
 
 1436            ilist2(i:new_size) = ilist2(i + 1:ndim)
 
 1441               ilist3(i:new_size) = ilist3(i + 1:ndim)
 
 1444               ilist3(i:new_size) = ilist3(i + 1:ndim)
 
 1445               ilist4(i:new_size) = ilist4(i + 1:ndim)
 
 1456   END SUBROUTINE check_element_list
 
 1466   SUBROUTINE add_bonds_list(conn_info, atm1, atm2, n_bonds)
 
 1468      INTEGER, 
INTENT(IN)                                :: atm1, atm2, n_bonds
 
 1470      INTEGER                                            :: new_size, old_size
 
 1472      old_size = 
SIZE(conn_info%bond_a)
 
 1473      IF (n_bonds > old_size) 
THEN 
 1474         new_size = int(5 + 1.2*old_size)
 
 1475         CALL reallocate(conn_info%bond_a, 1, new_size)
 
 1476         CALL reallocate(conn_info%bond_b, 1, new_size)
 
 1478      conn_info%bond_a(n_bonds) = atm1
 
 1479      conn_info%bond_b(n_bonds) = atm2
 
 1480   END SUBROUTINE add_bonds_list
 
 1492      CHARACTER(len=*), 
PARAMETER :: routinen = 
'topology_generate_bend' 
 1494      INTEGER                                            :: handle, handle2, i, iw, natom, nbond, &
 
 1495                                                            nsize, ntheta, output_unit
 
 1504                                extension=
".subsysLog")
 
 1505      CALL timeset(routinen, handle)
 
 1512      IF (
ASSOCIATED(conn_info%bond_a)) 
THEN 
 1513         nbond = 
SIZE(conn_info%bond_a)
 
 1518      IF (nbond /= 0) 
THEN 
 1519         nsize = int(5 + 1.2*ntheta)
 
 1524         ALLOCATE (bond_list(natom))
 
 1526            ALLOCATE (bond_list(i)%array1(0))
 
 1530         CALL timeset(routinen//
"_1", handle2)
 
 1531         CALL match_iterative_path(iarray1=bond_list, &
 
 1532                                   iarray2=bond_list, &
 
 1535                                   oarray1=conn_info%theta_a, &
 
 1536                                   oarray2=conn_info%theta_b, &
 
 1537                                   oarray3=conn_info%theta_c)
 
 1538         CALL timestop(handle2)
 
 1540            DEALLOCATE (bond_list(i)%array1)
 
 1542         DEALLOCATE (bond_list)
 
 1543         IF (output_unit > 0) 
THEN 
 1544            WRITE (output_unit, 
'(T2,"GENERATE|",1X,A,T71,I10)') 
" Preliminary Number of Bends generated:", &
 
 1549         CALL connectivity_external_control(section=bend_section, &
 
 1550                                            iarray1=conn_info%theta_a, &
 
 1551                                            iarray2=conn_info%theta_b, &
 
 1552                                            iarray3=conn_info%theta_c, &
 
 1555                                            output_unit=output_unit)
 
 1558      CALL reallocate(conn_info%theta_a, 1, ntheta)
 
 1559      CALL reallocate(conn_info%theta_b, 1, ntheta)
 
 1560      CALL reallocate(conn_info%theta_c, 1, ntheta)
 
 1561      IF (output_unit > 0 .AND. ntheta > 0) 
THEN 
 1562         WRITE (output_unit, 
'(T2,"GENERATE|",1X,A,T71,I10)') 
" Number of Bends generated:", &
 
 1565      CALL timestop(handle)
 
 1567                                        "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
 
 
 1587   RECURSIVE SUBROUTINE match_iterative_path(Iarray1, Iarray2, Iarray3, &
 
 1588                                             max_levl, Oarray1, Oarray2, Oarray3, Oarray4, Ilist, it_levl, nvar)
 
 1591         POINTER                                         :: iarray2, iarray3
 
 1592      INTEGER, 
INTENT(IN)                                :: max_levl
 
 1593      INTEGER, 
DIMENSION(:), 
POINTER                     :: oarray1, oarray2
 
 1594      INTEGER, 
DIMENSION(:), 
OPTIONAL, 
POINTER           :: oarray3, oarray4
 
 1595      INTEGER, 
DIMENSION(:), 
INTENT(INOUT), 
OPTIONAL     :: ilist
 
 1596      INTEGER, 
INTENT(IN), 
OPTIONAL                      :: it_levl
 
 1597      INTEGER, 
INTENT(INOUT)                             :: nvar
 
 1599      INTEGER                                            :: i, ind, j, my_levl, natom
 
 1600      INTEGER, 
ALLOCATABLE, 
DIMENSION(:)                 :: my_list
 
 1604      check = max_levl >= 2 .AND. max_levl <= 4
 
 1606      IF (.NOT. 
PRESENT(ilist)) 
THEN 
 1607         SELECT CASE (max_levl)
 
 1609            cpassert(.NOT. 
PRESENT(iarray2))
 
 1610            cpassert(.NOT. 
PRESENT(iarray3))
 
 1611            cpassert(.NOT. 
PRESENT(oarray3))
 
 1612            cpassert(.NOT. 
PRESENT(oarray4))
 
 1614            cpassert(
PRESENT(iarray2))
 
 1615            cpassert(.NOT. 
PRESENT(iarray3))
 
 1616            cpassert(
PRESENT(oarray3))
 
 1617            cpassert(.NOT. 
PRESENT(oarray4))
 
 1619            cpassert(
PRESENT(iarray2))
 
 1620            cpassert(
PRESENT(iarray3))
 
 1621            cpassert(
PRESENT(oarray3))
 
 1622            cpassert(
PRESENT(oarray4))
 
 1625      natom = 
SIZE(iarray1)
 
 1626      IF (.NOT. 
PRESENT(ilist)) 
THEN 
 1628         ALLOCATE (my_list(max_levl))
 
 1632            my_list(my_levl) = i
 
 1633            CALL match_iterative_path(iarray1=iarray1, &
 
 1636                                      it_levl=my_levl + 1, &
 
 1637                                      max_levl=max_levl, &
 
 1645         DEALLOCATE (my_list)
 
 1647         SELECT CASE (it_levl)
 
 1655         i = ilist(it_levl - 1)
 
 1656         DO j = 1, 
SIZE(iarray1(i)%array1)
 
 1657            ind = wrk(i)%array1(j)
 
 1658            IF (any(ilist == ind)) cycle
 
 1659            IF (it_levl < max_levl) 
THEN 
 1660               ilist(it_levl) = ind
 
 1661               CALL match_iterative_path(iarray1=iarray1, &
 
 1664                                         it_levl=it_levl + 1, &
 
 1665                                         max_levl=max_levl, &
 
 1673            ELSEIF (it_levl == max_levl) 
THEN 
 1674               IF (ilist(1) > ind) cycle
 
 1675               ilist(it_levl) = ind
 
 1677               SELECT CASE (it_levl)
 
 1679                  IF (nvar > 
SIZE(oarray1)) 
THEN 
 1680                     CALL reallocate(oarray1, 1, int(5 + 1.2*nvar))
 
 1681                     CALL reallocate(oarray2, 1, int(5 + 1.2*nvar))
 
 1683                  oarray1(nvar) = ilist(1)
 
 1684                  oarray2(nvar) = ilist(2)
 
 1686                  IF (nvar > 
SIZE(oarray1)) 
THEN 
 1687                     CALL reallocate(oarray1, 1, int(5 + 1.2*nvar))
 
 1688                     CALL reallocate(oarray2, 1, int(5 + 1.2*nvar))
 
 1689                     CALL reallocate(oarray3, 1, int(5 + 1.2*nvar))
 
 1691                  oarray1(nvar) = ilist(1)
 
 1692                  oarray2(nvar) = ilist(2)
 
 1693                  oarray3(nvar) = ilist(3)
 
 1695                  IF (nvar > 
SIZE(oarray1)) 
THEN 
 1696                     CALL reallocate(oarray1, 1, int(5 + 1.2*nvar))
 
 1697                     CALL reallocate(oarray2, 1, int(5 + 1.2*nvar))
 
 1698                     CALL reallocate(oarray3, 1, int(5 + 1.2*nvar))
 
 1699                     CALL reallocate(oarray4, 1, int(5 + 1.2*nvar))
 
 1701                  oarray1(nvar) = ilist(1)
 
 1702                  oarray2(nvar) = ilist(2)
 
 1703                  oarray3(nvar) = ilist(3)
 
 1704                  oarray4(nvar) = ilist(4)
 
 1716   END SUBROUTINE match_iterative_path
 
 1729      CHARACTER(len=*), 
PARAMETER :: routinen = 
'topology_generate_ub' 
 1731      INTEGER                                            :: handle, itheta, iw, ntheta, output_unit
 
 1738                                extension=
".subsysLog")
 
 1740      CALL timeset(routinen, handle)
 
 1742      ntheta = 
SIZE(conn_info%theta_a)
 
 1747      DO itheta = 1, ntheta
 
 1748         conn_info%ub_a(itheta) = conn_info%theta_a(itheta)
 
 1749         conn_info%ub_b(itheta) = conn_info%theta_b(itheta)
 
 1750         conn_info%ub_c(itheta) = conn_info%theta_c(itheta)
 
 1752      IF (output_unit > 0 .AND. ntheta > 0) 
THEN 
 1753         WRITE (output_unit, 
'(T2,"GENERATE|",1X,A,T71,I10)') 
" Number of UB generated:", &
 
 1756      CALL timestop(handle)
 
 1758                                        "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
 
 
 1772      CHARACTER(len=*), 
PARAMETER :: routinen = 
'topology_generate_dihe' 
 1774      INTEGER                                            :: handle, i, iw, natom, nbond, nphi, &
 
 1784                                extension=
".subsysLog")
 
 1786      CALL timeset(routinen, handle)
 
 1789      nbond = 
SIZE(conn_info%bond_a)
 
 1790      IF (nbond /= 0) 
THEN 
 1791         nsize = int(5 + 1.2*nphi)
 
 1798         ALLOCATE (bond_list(natom))
 
 1800            ALLOCATE (bond_list(i)%array1(0))
 
 1804         CALL match_iterative_path(iarray1=bond_list, &
 
 1805                                   iarray2=bond_list, &
 
 1806                                   iarray3=bond_list, &
 
 1809                                   oarray1=conn_info%phi_a, &
 
 1810                                   oarray2=conn_info%phi_b, &
 
 1811                                   oarray3=conn_info%phi_c, &
 
 1812                                   oarray4=conn_info%phi_d)
 
 1814            DEALLOCATE (bond_list(i)%array1)
 
 1816         DEALLOCATE (bond_list)
 
 1817         IF (output_unit > 0) 
THEN 
 1818            WRITE (output_unit, 
'(T2,"GENERATE|",1X,A,T71,I10)') 
" Preliminary Number of Torsions generated:", &
 
 1823         CALL connectivity_external_control(section=torsion_section, &
 
 1824                                            iarray1=conn_info%phi_a, &
 
 1825                                            iarray2=conn_info%phi_b, &
 
 1826                                            iarray3=conn_info%phi_c, &
 
 1827                                            iarray4=conn_info%phi_d, &
 
 1830                                            output_unit=output_unit)
 
 1837      IF (output_unit > 0 .AND. nphi > 0) 
THEN 
 1838         WRITE (output_unit, 
'(T2,"GENERATE|",1X,A,T71,I10)') 
" Number of Torsions generated:", &
 
 1841      CALL timestop(handle)
 
 1843                                        "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
 
 
 1857      CHARACTER(len=*), 
PARAMETER :: routinen = 
'topology_generate_impr' 
 1859      CHARACTER(LEN=2)                                   :: atm_symbol
 
 1860      INTEGER                                            :: handle, i, ind, iw, j, natom, nbond, &
 
 1861                                                            nimpr, nsize, output_unit
 
 1862      LOGICAL                                            :: accept_impr
 
 1872                                extension=
".subsysLog")
 
 1874      CALL timeset(routinen, handle)
 
 1879      nbond = 
SIZE(conn_info%bond_a)
 
 1880      IF (nbond /= 0) 
THEN 
 1881         nsize = int(5 + 1.2*nimpr)
 
 1887         ALLOCATE (bond_list(natom))
 
 1889            ALLOCATE (bond_list(i)%array1(0))
 
 1894            IF (
SIZE(bond_list(i)%array1) == 3) 
THEN 
 1897               accept_impr = .true.
 
 1898               atm_symbol = trim(
id2str(atom_info%id_element(i)))
 
 1900               IF (atm_symbol == 
"N ") 
THEN 
 1901                  accept_impr = .false.
 
 1905                     ind = bond_list(i)%array1(j)
 
 1906                     IF (
SIZE(bond_list(ind)%array1) == 3) accept_impr = .true.
 
 1909               IF (.NOT. accept_impr) cycle
 
 1911               IF (nimpr > 
SIZE(conn_info%impr_a)) 
THEN 
 1912                  nsize = int(5 + 1.2*nimpr)
 
 1918               conn_info%impr_a(nimpr) = i
 
 1919               conn_info%impr_b(nimpr) = bond_list(i)%array1(1)
 
 1920               conn_info%impr_c(nimpr) = bond_list(i)%array1(2)
 
 1921               conn_info%impr_d(nimpr) = bond_list(i)%array1(3)
 
 1925            DEALLOCATE (bond_list(i)%array1)
 
 1927         DEALLOCATE (bond_list)
 
 1930         CALL connectivity_external_control(section=impr_section, &
 
 1931                                            iarray1=conn_info%impr_a, &
 
 1932                                            iarray2=conn_info%impr_b, &
 
 1933                                            iarray3=conn_info%impr_c, &
 
 1934                                            iarray4=conn_info%impr_d, &
 
 1937                                            output_unit=output_unit, &
 
 1945      IF (output_unit > 0 .AND. nimpr > 0) 
THEN 
 1946         WRITE (output_unit, 
'(T2,"GENERATE|",1X,A,T71,I10)') 
" Number of Impropers generated:", &
 
 1949      CALL timestop(handle)
 
 1951                                        "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
 
 
 1964      CHARACTER(len=*), 
PARAMETER :: routinen = 
'topology_generate_onfo' 
 1966      INTEGER                                            :: atom_a, atom_b, handle, i, ionfo, iw, &
 
 1967                                                            natom, nbond, nphi, ntheta, output_unit
 
 1968      TYPE(
array1_list_type), 
DIMENSION(:), 
POINTER      :: bond_list, phi_list, theta_list
 
 1975                                extension=
".subsysLog")
 
 1977      CALL timeset(routinen, handle)
 
 1983      ALLOCATE (bond_list(natom))
 
 1985         ALLOCATE (bond_list(i)%array1(0))
 
 1987      nbond = 
SIZE(conn_info%bond_a)
 
 1991      ALLOCATE (theta_list(natom))
 
 1993         ALLOCATE (theta_list(i)%array1(0))
 
 1995      ntheta = 
SIZE(conn_info%theta_a)
 
 1996      CALL reorder_structure(theta_list, conn_info%theta_a, conn_info%theta_c, ntheta)
 
 1999      ALLOCATE (phi_list(natom))
 
 2001         ALLOCATE (phi_list(i)%array1(0))
 
 2003      nphi = 
SIZE(conn_info%phi_a)
 
 2011      DO atom_a = 1, natom
 
 2012         DO i = 1, 
SIZE(phi_list(atom_a)%array1)
 
 2013            atom_b = phi_list(atom_a)%array1(i)
 
 2015            IF (atom_a > atom_b) cycle
 
 2017            IF (any(atom_b == bond_list(atom_a)%array1)) cycle
 
 2019            IF (any(atom_b == theta_list(atom_a)%array1)) cycle
 
 2021            IF (any(atom_b == phi_list(atom_a)%array1(:i - 1))) cycle
 
 2023            conn_info%onfo_a(ionfo) = atom_a
 
 2024            conn_info%onfo_b(ionfo) = atom_b
 
 2034         DEALLOCATE (bond_list(i)%array1)
 
 2036      DEALLOCATE (bond_list)
 
 2039         DEALLOCATE (theta_list(i)%array1)
 
 2041      DEALLOCATE (theta_list)
 
 2044         DEALLOCATE (phi_list(i)%array1)
 
 2046      DEALLOCATE (phi_list)
 
 2049      IF (output_unit > 0 .AND. ionfo > 0) 
THEN 
 2050         WRITE (output_unit, 
'(T2,"GENERATE|",1X,A,T71,I10)') 
" Number of 1-4 interactions generated:", &
 
 2053      CALL timestop(handle)
 
 2055                                        "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
 
 
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
Define the atomic kind types and their sub types.
subroutine, public set_atomic_kind(atomic_kind, element_symbol, name, mass, kind_number, natom, atom_list, fist_potential, shell, shell_active, damping)
Set the components of an atomic kind data set.
subroutine, public deallocate_atomic_kind_set(atomic_kind_set)
Destructor routine for a set of atomic kinds.
Handles all functions related to the CELL.
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
real(kind=dp) function, public cp_unit_to_cp2k(value, unit_str, defaults, power)
converts to the internal cp2k units to the given unit
Define the neighbor list data types and the corresponding functionality.
subroutine, public fist_neighbor_deallocate(fist_neighbor)
...
Generate the atomic neighbor lists for FIST.
subroutine, public build_fist_neighbor_lists(atomic_kind_set, particle_set, local_particles, cell, r_max, r_minsq, ei_scale14, vdw_scale14, nonbonded, para_env, build_from_scratch, geo_check, mm_section, full_nl, exclusions)
...
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
An array-based list which grows on demand. When the internal array is full, a new array of twice the ...
Utility routines for the memory handling.
Interface to the message passing library MPI.
Define the data structure for the particle information.
subroutine, public deallocate_particle_set(particle_set)
Deallocate a particle set.
subroutine, public allocate_particle_set(particle_set, nparticle)
Allocate a particle set.
Periodic Table related data definitions.
subroutine, public get_ptable_info(symbol, number, amass, ielement, covalent_radius, metallic_radius, vdw_radius, found)
Pass information about the kind given the element symbol.
generates a unique id number for a string (str2id) that can be used two compare two strings....
character(len=default_string_length) function, public s2s(str)
converts a string in a string of default_string_length
integer function, public str2id(str)
returns a unique id for a given string, and stores the string for later retrieval using the id.
character(len=default_string_length) function, public id2str(id)
returns the string associated with a given id
Utilities for string manipulations.
subroutine, public integer_to_string(inumber, string)
Converts an integer number to a string. The WRITE statement will return an error message,...
elemental subroutine, public uppercase(string)
Convert all lower case characters in a string to upper case.
Collection of subroutine needed for topology related things.
subroutine, public topology_generate_impr(topology, subsys_section)
Using a list of bends, generate a list of impr.
subroutine, public topology_generate_onfo(topology, subsys_section)
Using a list of torsion, generate a list of onfo.
subroutine, public topology_generate_molname(conn_info, natom, natom_prev, nbond_prev, id_molname)
Generates molnames: useful when the connectivity on file does not provide them.
subroutine, public topology_generate_bend(topology, subsys_section)
Using a list of bonds, generate a list of bends.
subroutine, public topology_generate_molecule(topology, qmmm, qmmm_env, subsys_section)
Use information from bond list to generate molecule. (ie clustering)
subroutine, public topology_generate_dihe(topology, subsys_section)
Generate a list of torsions from bonds.
subroutine, public topology_generate_ub(topology, subsys_section)
The list of Urey-Bradley is equal to the list of bends.
subroutine, public topology_generate_bond(topology, para_env, subsys_section)
Use info from periodic table and assumptions to generate bonds.
Collection of subroutine needed for topology related things.
subroutine, public find_molecule(atom_bond_list, mol_info, mol_name)
each atom will be assigned a molecule number based on bonded fragments The array mol_info should be i...
recursive subroutine, public give_back_molecule(icheck, bond_list, i, mol_natom, mol_map, my_mol)
...
recursive subroutine, public reorder_list_array(ilist1, ilist2, ilist3, ilist4, nsize, ndim)
Order arrays of lists.
Control for reading in different topologies and coordinates.
All kind of helpful little routines.
Provides all information about an atomic kind.
type of a logger, at the moment it contains just a print level starting at which level it should be l...
stores all the informations relevant to an mpi environment