64#include "./base/base_uses.f90"
68 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'topology_generate_util'
71 LOGICAL,
PARAMETER :: debug_this_module = .false.
97 INTEGER,
INTENT(IN) :: natom, natom_prev, nbond_prev
98 INTEGER,
DIMENSION(:),
INTENT(INOUT) :: id_molname
100 CHARACTER(LEN=default_string_length),
PARAMETER :: basename =
"MOL"
102 CHARACTER(LEN=default_string_length) :: molname
103 INTEGER :: i, id_undef, n, nmol
110 ALLOCATE (atom_bond_list(natom))
112 ALLOCATE (atom_bond_list(i)%array1(0))
115 IF (
ASSOCIATED(conn_info%bond_a)) n =
SIZE(conn_info%bond_a) - nbond_prev
116 CALL reorder_structure(atom_bond_list, conn_info%bond_a(nbond_prev + 1:) - natom_prev, &
117 conn_info%bond_b(nbond_prev + 1:) - natom_prev, n)
121 check = all(id_molname == id_undef) .OR. all(id_molname /= id_undef)
124 IF (id_molname(i) == id_undef)
THEN
126 CALL generate_molname_low(i, atom_bond_list, molname, id_molname)
131 DEALLOCATE (atom_bond_list(i)%array1)
133 DEALLOCATE (atom_bond_list)
146 RECURSIVE SUBROUTINE generate_molname_low(i, atom_bond_list, molname, id_molname)
147 INTEGER,
INTENT(IN) :: i
149 CHARACTER(LEN=default_string_length),
INTENT(IN) :: molname
150 INTEGER,
DIMENSION(:),
INTENT(INOUT) :: id_molname
154 IF (debug_this_module)
THEN
155 WRITE (*, *)
"Entered with :", i
156 WRITE (*, *) trim(molname)//
": entering with i:", i,
" full series to test:: ", atom_bond_list(i)%array1
157 IF ((trim(
id2str(id_molname(i))) /=
"__UNDEF__") .AND. &
158 (trim(
id2str(id_molname(i))) /= trim(molname)))
THEN
159 WRITE (*, *)
"Atom (", i,
") has already a molecular name assigned ! ("//trim(
id2str(id_molname(i)))//
")."
160 WRITE (*, *)
"New molecular name would be: ("//trim(molname)//
")."
161 cpabort(
"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)
603 extension=
".subsysLog")
605 ALLOCATE (isolated_atoms(0))
613 CALL reallocate(isolated_atoms, 1,
SIZE(isolated_atoms) +
SIZE(tmp_v))
614 isolated_atoms(
SIZE(isolated_atoms) -
SIZE(tmp_v) + 1:
SIZE(isolated_atoms)) = tmp_v
619 bondparm_factor =
topology%bondparm_factor
624 ALLOCATE (radius(natom))
625 ALLOCATE (
list(natom))
626 ALLOCATE (h_list(natom))
627 ALLOCATE (pbc_coord(3, natom))
629 CALL timeset(trim(routinen)//
"_1", handle2)
632 upper_sym_1 = trim(
id2str(atom_info%id_element(iatom)))
634 CALL get_ptable_info(symbol=upper_sym_1, covalent_radius=radius(iatom))
638 cpabort(
"Illegal bondparm_type")
640 IF (upper_sym_1 ==
"H ") h_list(iatom) = .true.
642 IF (any(isolated_atoms == iatom)) radius(iatom) = 0.0_dp
644 IF (iw > 0)
WRITE (iw,
'(T2,"GENERATE|",5X,A,T50,A5,T60,A,T69,F12.6)') &
645 "In topology_generate_bond :: iatom = ", upper_sym_1, &
646 "radius:", radius(iatom)
648 CALL timestop(handle2)
649 CALL timeset(trim(routinen)//
"_2", handle2)
652 ALLOCATE (atomic_kind_set(1))
655 my_maxrad = maxval(radius)*2.0_dp
656 atomic_kind => atomic_kind_set(1)
658 name=
"XXX", element_symbol=
"XXX", mass=0.0_dp, atom_list=
list)
661 IF (my_maxrad*bondparm_factor > r_max(1, 1) .AND. (.NOT.
topology%molname_generated))
THEN
662 IF (output_unit > 0)
THEN
663 WRITE (output_unit,
'(T2,"GENERATE|",A)') &
664 " ERROR in connectivity generation!", &
665 " The THRESHOLD to select possible bonds is larger than the max. bondlength", &
666 " used to build the neighbors lists. Increase the BONDLENGTH_MAX parameter"
667 WRITE (output_unit,
'(T2,"GENERATE|",2(A,F11.6),A)') &
668 " Present THRESHOLD (", my_maxrad*bondparm_factor,
" )."// &
669 " Present BONDLENGTH_MAX (", r_max(1, 1),
" )"
671 cpabort(
"Unable to generate connectivity")
674 particle_set(i)%atomic_kind => atomic_kind_set(1)
675 particle_set(i)%r(1) = atom_info%r(1, i)
676 particle_set(i)%r(2) = atom_info%r(2, i)
677 particle_set(i)%r(3) = atom_info%r(3, i)
678 pbc_coord(:, i) =
pbc(atom_info%r(:, i),
topology%cell)
682 CALL timestop(handle2)
683 CALL timeset(trim(routinen)//
"_3", handle2)
685 cell=
topology%cell, r_max=r_max, r_minsq=r_minsq, &
686 ei_scale14=1.0_dp, vdw_scale14=1.0_dp, nonbonded=nonbonded, &
687 para_env=para_env, build_from_scratch=.true., geo_check=.true., &
688 mm_section=generate_section)
690 WRITE (iw,
'(T2,"GENERATE| Number of prescreened bonds (neighbors):",T71,I10)') &
691 nonbonded%neighbor_kind_pairs(1)%npairs
694 DO i = 1,
SIZE(nonbonded%neighbor_kind_pairs)
695 npairs = npairs + nonbonded%neighbor_kind_pairs(i)%npairs
697 ALLOCATE (bond_a(npairs))
698 ALLOCATE (bond_b(npairs))
699 ALLOCATE (map_nb(npairs))
701 DO j = 1,
SIZE(nonbonded%neighbor_kind_pairs)
702 DO i = 1, nonbonded%neighbor_kind_pairs(j)%npairs
704 bond_a(idim) = nonbonded%neighbor_kind_pairs(j)%list(1, i)
705 bond_b(idim) = nonbonded%neighbor_kind_pairs(j)%list(2, i)
709 CALL timestop(handle2)
710 CALL timeset(trim(routinen)//
"_4", handle2)
712 ALLOCATE (bond_list(natom))
714 ALLOCATE (bond_list(i)%array1(0))
715 ALLOCATE (bond_list(i)%array2(0))
726 connectivity_ok = .false.
730 atom_info%id_molname =
str2id(
s2s(
"TO_DEFINE_LATER"))
736 DO WHILE (.NOT. connectivity_ok)
740 IF (h_list(iatm1)) cycle
741 DO j = 1,
SIZE(bond_list(iatm1)%array1)
742 iatm2 = bond_list(iatm1)%array1(j)
743 IF (atom_info%id_molname(iatm1) /= atom_info%id_molname(iatm2)) cycle
744 IF (h_list(iatm2) .OR. (iatm2 <= iatm1)) cycle
745 k = bond_list(iatm1)%array2(j)
746 ksign = sign(1.0_dp, real(k, kind=
dp))
748 cell_v = matmul(
topology%cell%hmat, &
749 REAL(nonbonded%neighbor_kind_pairs(k)%cell_vector, kind=
dp))
750 dr = pbc_coord(:, iatm1) - pbc_coord(:, iatm2) - ksign*cell_v
751 r2 = dot_product(dr, dr)
752 IF (r2 <= r_minsq(1, 1))
THEN
753 CALL cp_abort(__location__, &
754 "bond distance between atoms less then the smallest distance provided "// &
758 IF ((any(isolated_atoms == iatm1)) .OR. (any(isolated_atoms == iatm2))) cycle
762 rbond = radius(iatm1) + radius(iatm2)
764 rbond = max(radius(iatm1), radius(iatm2))
767 rbond2 = rbond2*(bondparm_factor)**2
769 IF (r2 <= rbond2)
THEN
770 n_heavy_bonds = n_heavy_bonds + 1
771 CALL add_bonds_list(conn_info, iatm1, iatm2, n_heavy_bonds)
776 n_bonds = n_heavy_bonds
779 IF (output_unit > 0)
WRITE (output_unit, *)
781 IF (.NOT. h_list(iatm1)) cycle
782 r2_min = huge(0.0_dp)
785 DO j = 1,
SIZE(bond_list(iatm1)%array1)
786 iatm2 = bond_list(iatm1)%array1(j)
788 IF (atom_info%id_molname(iatm1) /= atom_info%id_molname(iatm2)) cycle
789 IF (h_list(iatm2) .AND. (iatm2 <= iatm1)) cycle
791 IF ((any(isolated_atoms == iatm1)) .OR. (any(isolated_atoms == iatm2))) cycle
793 k = bond_list(iatm1)%array2(j)
794 ksign = sign(1.0_dp, real(k, kind=
dp))
796 cell_v = matmul(
topology%cell%hmat, &
797 REAL(nonbonded%neighbor_kind_pairs(k)%cell_vector, kind=
dp))
798 dr = pbc_coord(:, iatm1) - pbc_coord(:, iatm2) - ksign*cell_v
799 r2 = dot_product(dr, dr)
800 IF (r2 <= r_minsq(1, 1))
THEN
801 CALL cp_abort(__location__, &
802 "bond distance between atoms less then the smallest distance provided "// &
805 IF (r2 <= r2_min)
THEN
810 IF (ibond == -1)
THEN
811 IF (output_unit > 0 .AND. print_info)
THEN
812 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,I10,A)') &
813 "WARNING:: No connections detected for Hydrogen - Atom Nr:", iatm1,
" !"
816 n_hydr_bonds = n_hydr_bonds + 1
817 n_bonds = n_bonds + 1
818 CALL add_bonds_list(conn_info, min(iatm1, ibond), max(iatm1, ibond), n_bonds)
821 IF (output_unit > 0)
THEN
822 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)') &
823 " Preliminary Number of Bonds generated:", n_bonds
827 CALL connectivity_external_control(section=bond_section, &
828 iarray1=conn_info%bond_a, &
829 iarray2=conn_info%bond_b, &
832 output_unit=output_unit)
839 IF (.NOT.
topology%reorder_atom)
THEN
841 IF (output_unit > 0)
WRITE (output_unit,
'(T2,"GENERATE|",A)') &
842 " Molecules names have been generated. Now reordering particle set in order to have ", &
843 " atoms belonging to the same molecule in a sequential order."
845 connectivity_ok = .true.
848 connectivity_ok = check_generate_mol(conn_info%bond_a, conn_info%bond_b, &
849 atom_info, bondparm_factor, output_unit)
851 IF (my_maxrad*bondparm_factor > r_max(1, 1) .AND. (.NOT.
topology%molname_generated))
THEN
852 IF (output_unit > 0)
THEN
853 WRITE (output_unit,
'(T2,"GENERATE|",A)') &
854 " ERROR in connectivity generation!", &
855 " The THRESHOLD to select possible bonds is bigger than the MAX bondlength", &
856 " used to build the neighbors lists. Increase the BONDLENGTH_MAX patameter"
857 WRITE (output_unit,
'(T2,"GENERATE|",2(A,F11.6),A)') &
858 " Present THRESHOLD (", my_maxrad*bondparm_factor,
" )."// &
859 " Present BONDLENGTH_MAX (", r_max(1, 1),
" )"
861 cpabort(
"Unable to generate connectivity")
864 IF (connectivity_ok .AND. (output_unit > 0))
THEN
865 WRITE (output_unit,
'(T2,"GENERATE|",A)') &
866 " Achieved consistency in connectivity generation."
869 CALL timestop(handle2)
870 CALL timeset(trim(routinen)//
"_6", handle2)
873 DEALLOCATE (bond_list(i)%array1)
874 DEALLOCATE (bond_list(i)%array2)
876 DEALLOCATE (bond_list)
877 DEALLOCATE (pbc_coord)
883 CALL timestop(handle2)
884 IF (output_unit > 0 .AND. n_bonds > 0)
THEN
885 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Number of Bonds generated:", &
888 CALL timeset(trim(routinen)//
"_7", handle2)
893 DO ibond = 1,
SIZE(conn_info%bond_a)
894 iatom = conn_info%bond_a(ibond)
895 jatom = conn_info%bond_b(ibond)
896 IF ((atom_info%id_molname(iatom) /= atom_info%id_molname(jatom)) .OR. &
897 (atom_info%resid(iatom) /= atom_info%resid(jatom)) .OR. &
898 (atom_info%id_resname(iatom) /= atom_info%id_resname(jatom)))
THEN
899 IF (iw > 0)
WRITE (iw, *)
" PARA_RES, bond between molecules atom ", &
904 conn_info%c_bond_a(cbond) = iatom
905 conn_info%c_bond_b(cbond) = jatom
907 IF (atom_info%id_molname(iatom) /= atom_info%id_molname(jatom))
THEN
908 cpabort(
"Bonds between different molecule types?")
913 CALL timestop(handle2)
914 DEALLOCATE (isolated_atoms)
915 CALL timestop(handle)
917 "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
930 FUNCTION check_generate_mol(bond_a, bond_b, atom_info, bondparm_factor, output_unit) &
932 INTEGER,
DIMENSION(:),
POINTER :: bond_a, bond_b
934 REAL(kind=
dp),
INTENT(INOUT) :: bondparm_factor
935 INTEGER,
INTENT(IN) :: output_unit
938 CHARACTER(len=*),
PARAMETER :: routinen =
'check_generate_mol'
940 CHARACTER(LEN=10) :: ctmp1, ctmp2, ctmp3
941 INTEGER :: handle, i, idim, itype, j, mol_natom, &
943 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: mol_info_tmp
944 INTEGER,
DIMENSION(:),
POINTER :: mol_map, mol_map_o, wrk
945 INTEGER,
DIMENSION(:, :),
POINTER :: mol_info
946 LOGICAL,
DIMENSION(:),
POINTER :: icheck
949 CALL timeset(routinen, handle)
951 natom =
SIZE(atom_info%id_atmname)
952 ALLOCATE (bond_list(natom))
954 ALLOCATE (bond_list(i)%array1(0))
957 ALLOCATE (mol_map(natom))
958 ALLOCATE (mol_map_o(natom))
959 ALLOCATE (wrk(natom))
962 mol_map(i) = atom_info%id_molname(i)
966 CALL sort(mol_map, natom, wrk)
980 ALLOCATE (mol_info_tmp(natom, 2))
985 mol_info_tmp(1, 1) = itype
987 IF (mol_map(i) /= itype)
THEN
990 mol_info_tmp(nsize, 1) = itype
991 mol_info_tmp(nsize - 1, 2) = idim
997 mol_info_tmp(nsize, 2) = idim
999 ALLOCATE (mol_info(nsize, 4))
1000 mol_info(1:nsize, 1:2) = mol_info_tmp(1:nsize, 1:2)
1001 DEALLOCATE (mol_info_tmp)
1008 ALLOCATE (icheck(natom))
1011 IF (icheck(i)) cycle
1012 itype = mol_map_o(i)
1015 DO j = 1,
SIZE(mol_info)
1016 IF (itype == mol_info(j, 1))
EXIT
1018 mol_info(j, 3) = mol_info(j, 3) + 1
1019 IF (mol_info(j, 4) == 0) mol_info(j, 4) = mol_natom
1020 IF (mol_info(j, 4) /= mol_natom)
THEN
1026 bondparm_factor = bondparm_factor*1.05_dp
1027 IF (output_unit < 0)
EXIT
1028 WRITE (output_unit,
'(/,T2,"GENERATE|",A)')
" WARNING in connectivity generation!"
1029 WRITE (output_unit,
'(T2,"GENERATE|",A)') &
1030 ' Two molecules/residues named ('//trim(
id2str(itype))//
') have different '// &
1035 WRITE (output_unit,
'(T2,"GENERATE|",A)')
' Molecule starting at position ('// &
1036 trim(ctmp1)//
') has Nr. <'//trim(ctmp2)// &
1037 '> of atoms.',
' while the other same molecules have Nr. <'// &
1038 trim(ctmp3)//
'> of atoms!'
1039 WRITE (output_unit,
'(T2,"GENERATE|",A)') &
1040 ' Increasing bondparm_factor by 1.05.. An error was found in the generated', &
1041 ' connectivity. Retry...'
1042 WRITE (output_unit,
'(T2,"GENERATE|",A,F11.6,A,/)') &
1043 " Present value of BONDPARM_FACTOR (", bondparm_factor,
" )."
1049 DEALLOCATE (mol_info)
1050 DEALLOCATE (mol_map)
1051 DEALLOCATE (mol_map_o)
1054 DEALLOCATE (bond_list(i)%array1)
1056 DEALLOCATE (bond_list)
1057 CALL timestop(handle)
1058 END FUNCTION check_generate_mol
1074 SUBROUTINE connectivity_external_control(section, Iarray1, Iarray2, Iarray3, Iarray4, nvar, &
1075 topology, output_unit, is_impr)
1077 INTEGER,
DIMENSION(:),
POINTER :: iarray1, iarray2
1078 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: iarray3, iarray4
1079 INTEGER,
INTENT(INOUT) :: nvar
1081 INTEGER,
INTENT(IN) :: output_unit
1082 LOGICAL,
INTENT(IN),
OPTIONAL :: is_impr
1084 CHARACTER(LEN=8) :: fmt
1085 INTEGER :: do_action, do_it, i, j, k, n_rep, &
1086 n_rep_val, natom, new_size, nsize
1087 INTEGER,
DIMENSION(:),
POINTER :: atlist, ilist1, ilist2, ilist3, ilist4
1088 LOGICAL :: explicit, ip3, ip4
1092 ip3 =
PRESENT(iarray3)
1093 ip4 =
PRESENT(iarray4)
1095 IF (ip3) nsize = nsize + 1
1096 IF (ip3 .AND. ip4) nsize = nsize + 1
1102 NULLIFY (ilist1, ilist2, ilist3, ilist4, atlist)
1103 ALLOCATE (ilist1(nvar))
1104 ALLOCATE (ilist2(nvar))
1105 ilist1 = iarray1(1:nvar)
1106 ilist2 = iarray2(1:nvar)
1110 ALLOCATE (ilist3(nvar))
1111 ilist3 = iarray3(1:nvar)
1113 ALLOCATE (ilist3(nvar))
1114 ALLOCATE (ilist4(nvar))
1115 ilist3 = iarray3(1:nvar)
1116 ilist4 = iarray4(1:nvar)
1119 cpabort(
"Only 2, 3, 4 are supported as the value of nsize")
1121 CALL list_canonical_order(ilist1, ilist2, ilist3, ilist4, nsize, is_impr)
1131 cpassert(
SIZE(atlist) == nsize)
1133 CALL check_element_list(do_it, do_action, atlist, ilist1, ilist2, ilist3, ilist4, &
1135 IF (do_action ==
do_add)
THEN
1139 IF (output_unit > 0)
THEN
1140 WRITE (output_unit,
'(T2,"ADD|",1X,A,I6,'//trim(fmt)//
'(A,I6),A,T64,A,I6)') &
1142 atlist(1), (
",", atlist(k), k=2, nsize),
") added.",
" NEW size::", nvar
1144 IF (nvar >
SIZE(iarray1))
THEN
1145 new_size = int(5 + 1.2*nvar)
1157 iarray1(do_it + 1:nvar) = iarray1(do_it:nvar - 1)
1158 iarray2(do_it + 1:nvar) = iarray2(do_it:nvar - 1)
1159 iarray1(do_it) = ilist1(do_it)
1160 iarray2(do_it) = ilist2(do_it)
1163 iarray3(do_it + 1:nvar) = iarray3(do_it:nvar - 1)
1164 iarray3(do_it) = ilist3(do_it)
1166 iarray3(do_it + 1:nvar) = iarray3(do_it:nvar - 1)
1167 iarray4(do_it + 1:nvar) = iarray4(do_it:nvar - 1)
1168 iarray3(do_it) = ilist3(do_it)
1169 iarray4(do_it) = ilist4(do_it)
1172 IF (output_unit > 0)
THEN
1173 WRITE (output_unit,
'(T2,"ADD|",1X,A,I6,'//trim(fmt)//
'(A,I6),A,T80,A)') &
1175 atlist(1), (
",", atlist(k), k=2, nsize),
") already found.",
"X"
1182 IF (output_unit > 0)
THEN
1183 WRITE (output_unit,
'(T2,"RMV|",1X,A,I6,'//trim(fmt)//
'(A,I6),A,T64,A,I6)') &
1185 atlist(1), (
",", atlist(k), k=2, nsize),
") removed.",
" NEW size::", nvar
1187 iarray1(do_it:nvar) = iarray1(do_it + 1:nvar + 1)
1188 iarray2(do_it:nvar) = iarray2(do_it + 1:nvar + 1)
1189 iarray1(nvar + 1) = -huge(0)
1190 iarray2(nvar + 1) = -huge(0)
1193 iarray3(do_it:nvar) = iarray3(do_it + 1:nvar + 1)
1194 iarray3(nvar + 1) = -huge(0)
1196 iarray3(do_it:nvar) = iarray3(do_it + 1:nvar + 1)
1197 iarray4(do_it:nvar) = iarray4(do_it + 1:nvar + 1)
1198 iarray3(nvar + 1) = -huge(0)
1199 iarray4(nvar + 1) = -huge(0)
1202 IF (output_unit > 0)
THEN
1203 WRITE (output_unit,
'(T2,"RMV|",1X,A,I6,'//trim(fmt)//
'(A,I6),A,T80,A)') &
1205 atlist(1), (
",", atlist(k), k=2, nsize),
") not found.",
"X"
1223 cpabort(
"Only 2, 3, 4 are supported as the value of nsize")
1226 END SUBROUTINE connectivity_external_control
1239 SUBROUTINE list_canonical_order(Ilist1, Ilist2, Ilist3, Ilist4, nsize, is_impr)
1240 INTEGER,
DIMENSION(:),
POINTER :: ilist1, ilist2
1241 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: ilist3, ilist4
1242 INTEGER,
INTENT(IN) :: nsize
1243 LOGICAL,
INTENT(IN),
OPTIONAL :: is_impr
1245 INTEGER :: i, ss(3), tmp1, tmp2, tmp3, tt(3)
1249 IF (
PRESENT(is_impr)) do_impr = is_impr
1252 DO i = 1,
SIZE(ilist1)
1255 ilist1(i) = min(tmp1, tmp2)
1256 ilist2(i) = max(tmp1, tmp2)
1259 DO i = 1,
SIZE(ilist1)
1262 ilist1(i) = min(tmp1, tmp2)
1263 ilist3(i) = max(tmp1, tmp2)
1266 DO i = 1,
SIZE(ilist1)
1267 IF (.NOT. do_impr)
THEN
1270 ilist1(i) = min(tmp1, tmp2)
1271 IF (ilist1(i) == tmp2)
THEN
1273 ilist3(i) = ilist2(i)
1276 ilist4(i) = max(tmp1, tmp2)
1281 CALL sort(tt, 3, ss)
1289 END SUBROUTINE list_canonical_order
1303 SUBROUTINE check_element_list(do_it, do_action, atlist, Ilist1, Ilist2, Ilist3, Ilist4, &
1305 INTEGER,
INTENT(OUT) :: do_it
1306 INTEGER,
INTENT(IN) :: do_action
1307 INTEGER,
DIMENSION(:),
POINTER :: atlist, ilist1, ilist2
1308 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: ilist3, ilist4
1309 LOGICAL,
INTENT(IN),
OPTIONAL :: is_impr
1311 INTEGER :: i, iend, istart, ndim, new_size, nsize, &
1312 ss(3), tmp1, tmp2, tmp3, tt(3)
1313 INTEGER,
DIMENSION(4) :: tmp
1314 LOGICAL :: do_impr, found
1317 IF (
PRESENT(is_impr)) do_impr = is_impr
1319 nsize =
SIZE(atlist)
1328 tmp(1) = min(tmp1, tmp2)
1329 tmp(2) = max(tmp1, tmp2)
1333 tmp(1) = min(tmp1, tmp2)
1334 tmp(3) = max(tmp1, tmp2)
1336 IF (.NOT. do_impr)
THEN
1339 tmp(1) = min(tmp1, tmp2)
1340 IF (tmp(1) == tmp2)
THEN
1345 tmp(4) = max(tmp1, tmp2)
1350 CALL sort(tt, 3, ss)
1358 IF (ilist1(istart) >= tmp(1))
EXIT
1361 IF (istart <= ndim)
THEN
1362 IF (ilist1(istart) > tmp(1) .AND. (istart /= 1)) istart = istart - 1
1364 DO iend = istart, ndim
1365 IF (ilist1(iend) /= tmp(1))
EXIT
1367 IF (iend == ndim + 1) iend = ndim
1372 IF ((ilist1(i) > tmp(1)) .OR. (ilist2(i) > tmp(2)))
EXIT
1373 IF ((ilist1(i) == tmp(1)) .AND. (ilist2(i) == tmp(2)))
THEN
1380 IF ((ilist1(i) > tmp(1)) .OR. (ilist2(i) > tmp(2)) .OR. (ilist3(i) > tmp(3)))
EXIT
1381 IF ((ilist1(i) == tmp(1)) .AND. (ilist2(i) == tmp(2)) .AND. (ilist3(i) == tmp(3)))
THEN
1388 IF ((ilist1(i) > tmp(1)) .OR. (ilist2(i) > tmp(2)) .OR. (ilist3(i) > tmp(3)) .OR. (ilist4(i) > tmp(4)))
EXIT
1389 IF ((ilist1(i) == tmp(1)) .AND. (ilist2(i) == tmp(2)) &
1390 .AND. (ilist3(i) == tmp(3)) .AND. (ilist4(i) == tmp(4)))
THEN
1396 SELECT CASE (do_action)
1413 ilist1(i + 1:new_size) = ilist1(i:ndim)
1414 ilist2(i + 1:new_size) = ilist2(i:ndim)
1420 ilist3(i + 1:new_size) = ilist3(i:ndim)
1425 ilist3(i + 1:new_size) = ilist3(i:ndim)
1426 ilist4(i + 1:new_size) = ilist4(i:ndim)
1436 ilist1(i:new_size) = ilist1(i + 1:ndim)
1437 ilist2(i:new_size) = ilist2(i + 1:ndim)
1442 ilist3(i:new_size) = ilist3(i + 1:ndim)
1445 ilist3(i:new_size) = ilist3(i + 1:ndim)
1446 ilist4(i:new_size) = ilist4(i + 1:ndim)
1457 END SUBROUTINE check_element_list
1467 SUBROUTINE add_bonds_list(conn_info, atm1, atm2, n_bonds)
1469 INTEGER,
INTENT(IN) :: atm1, atm2, n_bonds
1471 INTEGER :: new_size, old_size
1473 old_size =
SIZE(conn_info%bond_a)
1474 IF (n_bonds > old_size)
THEN
1475 new_size = int(5 + 1.2*old_size)
1476 CALL reallocate(conn_info%bond_a, 1, new_size)
1477 CALL reallocate(conn_info%bond_b, 1, new_size)
1479 conn_info%bond_a(n_bonds) = atm1
1480 conn_info%bond_b(n_bonds) = atm2
1481 END SUBROUTINE add_bonds_list
1493 CHARACTER(len=*),
PARAMETER :: routinen =
'topology_generate_bend'
1495 INTEGER :: handle, handle2, i, iw, natom, nbond, &
1496 nsize, ntheta, output_unit
1505 extension=
".subsysLog")
1506 CALL timeset(routinen, handle)
1513 IF (
ASSOCIATED(conn_info%bond_a))
THEN
1514 nbond =
SIZE(conn_info%bond_a)
1519 IF (nbond /= 0)
THEN
1520 nsize = int(5 + 1.2*ntheta)
1525 ALLOCATE (bond_list(natom))
1527 ALLOCATE (bond_list(i)%array1(0))
1531 CALL timeset(routinen//
"_1", handle2)
1532 CALL match_iterative_path(iarray1=bond_list, &
1533 iarray2=bond_list, &
1536 oarray1=conn_info%theta_a, &
1537 oarray2=conn_info%theta_b, &
1538 oarray3=conn_info%theta_c)
1539 CALL timestop(handle2)
1541 DEALLOCATE (bond_list(i)%array1)
1543 DEALLOCATE (bond_list)
1544 IF (output_unit > 0)
THEN
1545 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Preliminary Number of Bends generated:", &
1550 CALL connectivity_external_control(section=bend_section, &
1551 iarray1=conn_info%theta_a, &
1552 iarray2=conn_info%theta_b, &
1553 iarray3=conn_info%theta_c, &
1556 output_unit=output_unit)
1559 CALL reallocate(conn_info%theta_a, 1, ntheta)
1560 CALL reallocate(conn_info%theta_b, 1, ntheta)
1561 CALL reallocate(conn_info%theta_c, 1, ntheta)
1562 IF (output_unit > 0 .AND. ntheta > 0)
THEN
1563 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Number of Bends generated:", &
1566 CALL timestop(handle)
1568 "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
1588 RECURSIVE SUBROUTINE match_iterative_path(Iarray1, Iarray2, Iarray3, &
1589 max_levl, Oarray1, Oarray2, Oarray3, Oarray4, Ilist, it_levl, nvar)
1592 POINTER :: iarray2, iarray3
1593 INTEGER,
INTENT(IN) :: max_levl
1594 INTEGER,
DIMENSION(:),
POINTER :: oarray1, oarray2
1595 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: oarray3, oarray4
1596 INTEGER,
DIMENSION(:),
INTENT(INOUT),
OPTIONAL :: ilist
1597 INTEGER,
INTENT(IN),
OPTIONAL :: it_levl
1598 INTEGER,
INTENT(INOUT) :: nvar
1600 INTEGER :: i, ind, j, my_levl, natom
1601 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: my_list
1605 check = max_levl >= 2 .AND. max_levl <= 4
1607 IF (.NOT.
PRESENT(ilist))
THEN
1608 SELECT CASE (max_levl)
1610 cpassert(.NOT.
PRESENT(iarray2))
1611 cpassert(.NOT.
PRESENT(iarray3))
1612 cpassert(.NOT.
PRESENT(oarray3))
1613 cpassert(.NOT.
PRESENT(oarray4))
1615 cpassert(
PRESENT(iarray2))
1616 cpassert(.NOT.
PRESENT(iarray3))
1617 cpassert(
PRESENT(oarray3))
1618 cpassert(.NOT.
PRESENT(oarray4))
1620 cpassert(
PRESENT(iarray2))
1621 cpassert(
PRESENT(iarray3))
1622 cpassert(
PRESENT(oarray3))
1623 cpassert(
PRESENT(oarray4))
1626 natom =
SIZE(iarray1)
1627 IF (.NOT.
PRESENT(ilist))
THEN
1629 ALLOCATE (my_list(max_levl))
1633 my_list(my_levl) = i
1634 CALL match_iterative_path(iarray1=iarray1, &
1637 it_levl=my_levl + 1, &
1638 max_levl=max_levl, &
1646 DEALLOCATE (my_list)
1648 SELECT CASE (it_levl)
1656 i = ilist(it_levl - 1)
1657 DO j = 1,
SIZE(iarray1(i)%array1)
1658 ind = wrk(i)%array1(j)
1659 IF (any(ilist == ind)) cycle
1660 IF (it_levl < max_levl)
THEN
1661 ilist(it_levl) = ind
1662 CALL match_iterative_path(iarray1=iarray1, &
1665 it_levl=it_levl + 1, &
1666 max_levl=max_levl, &
1674 ELSE IF (it_levl == max_levl)
THEN
1675 IF (ilist(1) > ind) cycle
1676 ilist(it_levl) = ind
1678 SELECT CASE (it_levl)
1680 IF (nvar >
SIZE(oarray1))
THEN
1681 CALL reallocate(oarray1, 1, int(5 + 1.2*nvar))
1682 CALL reallocate(oarray2, 1, int(5 + 1.2*nvar))
1684 oarray1(nvar) = ilist(1)
1685 oarray2(nvar) = ilist(2)
1687 IF (nvar >
SIZE(oarray1))
THEN
1688 CALL reallocate(oarray1, 1, int(5 + 1.2*nvar))
1689 CALL reallocate(oarray2, 1, int(5 + 1.2*nvar))
1690 CALL reallocate(oarray3, 1, int(5 + 1.2*nvar))
1692 oarray1(nvar) = ilist(1)
1693 oarray2(nvar) = ilist(2)
1694 oarray3(nvar) = ilist(3)
1696 IF (nvar >
SIZE(oarray1))
THEN
1697 CALL reallocate(oarray1, 1, int(5 + 1.2*nvar))
1698 CALL reallocate(oarray2, 1, int(5 + 1.2*nvar))
1699 CALL reallocate(oarray3, 1, int(5 + 1.2*nvar))
1700 CALL reallocate(oarray4, 1, int(5 + 1.2*nvar))
1702 oarray1(nvar) = ilist(1)
1703 oarray2(nvar) = ilist(2)
1704 oarray3(nvar) = ilist(3)
1705 oarray4(nvar) = ilist(4)
1708 cpabort(
"Only 2, 3, 4 are supported as the value of it_levl")
1713 cpabort(
"it_levl exceeds max_levl in match_iterative_path")
1717 END SUBROUTINE match_iterative_path
1730 CHARACTER(len=*),
PARAMETER :: routinen =
'topology_generate_ub'
1732 INTEGER :: handle, itheta, iw, ntheta, output_unit
1739 extension=
".subsysLog")
1741 CALL timeset(routinen, handle)
1743 ntheta =
SIZE(conn_info%theta_a)
1748 DO itheta = 1, ntheta
1749 conn_info%ub_a(itheta) = conn_info%theta_a(itheta)
1750 conn_info%ub_b(itheta) = conn_info%theta_b(itheta)
1751 conn_info%ub_c(itheta) = conn_info%theta_c(itheta)
1753 IF (output_unit > 0 .AND. ntheta > 0)
THEN
1754 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Number of UB generated:", &
1757 CALL timestop(handle)
1759 "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
1773 CHARACTER(len=*),
PARAMETER :: routinen =
'topology_generate_dihe'
1775 INTEGER :: handle, i, iw, natom, nbond, nphi, &
1785 extension=
".subsysLog")
1787 CALL timeset(routinen, handle)
1790 nbond =
SIZE(conn_info%bond_a)
1791 IF (nbond /= 0)
THEN
1792 nsize = int(5 + 1.2*nphi)
1799 ALLOCATE (bond_list(natom))
1801 ALLOCATE (bond_list(i)%array1(0))
1805 CALL match_iterative_path(iarray1=bond_list, &
1806 iarray2=bond_list, &
1807 iarray3=bond_list, &
1810 oarray1=conn_info%phi_a, &
1811 oarray2=conn_info%phi_b, &
1812 oarray3=conn_info%phi_c, &
1813 oarray4=conn_info%phi_d)
1815 DEALLOCATE (bond_list(i)%array1)
1817 DEALLOCATE (bond_list)
1818 IF (output_unit > 0)
THEN
1819 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Preliminary Number of Torsions generated:", &
1824 CALL connectivity_external_control(section=torsion_section, &
1825 iarray1=conn_info%phi_a, &
1826 iarray2=conn_info%phi_b, &
1827 iarray3=conn_info%phi_c, &
1828 iarray4=conn_info%phi_d, &
1831 output_unit=output_unit)
1838 IF (output_unit > 0 .AND. nphi > 0)
THEN
1839 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Number of Torsions generated:", &
1842 CALL timestop(handle)
1844 "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
1858 CHARACTER(len=*),
PARAMETER :: routinen =
'topology_generate_impr'
1860 CHARACTER(LEN=2) :: atm_symbol
1861 INTEGER :: handle, i, ind, iw, j, natom, nbond, &
1862 nimpr, nsize, output_unit
1863 LOGICAL :: accept_impr
1873 extension=
".subsysLog")
1875 CALL timeset(routinen, handle)
1880 nbond =
SIZE(conn_info%bond_a)
1881 IF (nbond /= 0)
THEN
1882 nsize = int(5 + 1.2*nimpr)
1888 ALLOCATE (bond_list(natom))
1890 ALLOCATE (bond_list(i)%array1(0))
1895 IF (
SIZE(bond_list(i)%array1) == 3)
THEN
1898 accept_impr = .true.
1899 atm_symbol = trim(
id2str(atom_info%id_element(i)))
1901 IF (atm_symbol ==
"N ")
THEN
1902 accept_impr = .false.
1906 ind = bond_list(i)%array1(j)
1907 IF (
SIZE(bond_list(ind)%array1) == 3) accept_impr = .true.
1910 IF (.NOT. accept_impr) cycle
1912 IF (nimpr >
SIZE(conn_info%impr_a))
THEN
1913 nsize = int(5 + 1.2*nimpr)
1919 conn_info%impr_a(nimpr) = i
1920 conn_info%impr_b(nimpr) = bond_list(i)%array1(1)
1921 conn_info%impr_c(nimpr) = bond_list(i)%array1(2)
1922 conn_info%impr_d(nimpr) = bond_list(i)%array1(3)
1926 DEALLOCATE (bond_list(i)%array1)
1928 DEALLOCATE (bond_list)
1931 CALL connectivity_external_control(section=impr_section, &
1932 iarray1=conn_info%impr_a, &
1933 iarray2=conn_info%impr_b, &
1934 iarray3=conn_info%impr_c, &
1935 iarray4=conn_info%impr_d, &
1938 output_unit=output_unit, &
1946 IF (output_unit > 0 .AND. nimpr > 0)
THEN
1947 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Number of Impropers generated:", &
1950 CALL timestop(handle)
1952 "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
1965 CHARACTER(len=*),
PARAMETER :: routinen =
'topology_generate_onfo'
1967 INTEGER :: atom_a, atom_b, handle, i, ionfo, iw, &
1968 natom, nbond, nphi, ntheta, output_unit
1969 TYPE(
array1_list_type),
DIMENSION(:),
POINTER :: bond_list, phi_list, theta_list
1976 extension=
".subsysLog")
1978 CALL timeset(routinen, handle)
1984 ALLOCATE (bond_list(natom))
1986 ALLOCATE (bond_list(i)%array1(0))
1988 nbond =
SIZE(conn_info%bond_a)
1992 ALLOCATE (theta_list(natom))
1994 ALLOCATE (theta_list(i)%array1(0))
1996 ntheta =
SIZE(conn_info%theta_a)
1997 CALL reorder_structure(theta_list, conn_info%theta_a, conn_info%theta_c, ntheta)
2000 ALLOCATE (phi_list(natom))
2002 ALLOCATE (phi_list(i)%array1(0))
2004 nphi =
SIZE(conn_info%phi_a)
2012 DO atom_a = 1, natom
2013 DO i = 1,
SIZE(phi_list(atom_a)%array1)
2014 atom_b = phi_list(atom_a)%array1(i)
2016 IF (atom_a > atom_b) cycle
2018 IF (any(atom_b == bond_list(atom_a)%array1)) cycle
2020 IF (any(atom_b == theta_list(atom_a)%array1)) cycle
2022 IF (any(atom_b == phi_list(atom_a)%array1(:i - 1))) cycle
2024 conn_info%onfo_a(ionfo) = atom_a
2025 conn_info%onfo_b(ionfo) = atom_b
2035 DEALLOCATE (bond_list(i)%array1)
2037 DEALLOCATE (bond_list)
2040 DEALLOCATE (theta_list(i)%array1)
2042 DEALLOCATE (theta_list)
2045 DEALLOCATE (phi_list(i)%array1)
2047 DEALLOCATE (phi_list)
2050 IF (output_unit > 0 .AND. ionfo > 0)
THEN
2051 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Number of 1-4 interactions generated:", &
2054 CALL timestop(handle)
2056 "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,...
integer, parameter, public silent_print_level
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