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