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 cpabort(
"Detecting something wrong in the molecular setup!")
163 id_molname(i) =
str2id(molname)
164 DO j = 1,
SIZE(atom_bond_list(i)%array1)
165 k = atom_bond_list(i)%array1(j)
166 IF (debug_this_module)
WRITE (*, *)
"entering with i:", i,
"testing :", k
168 atom_bond_list(i)%array1(j) = -1
169 WHERE (atom_bond_list(k)%array1 == i) atom_bond_list(k)%array1 = -1
170 CALL generate_molname_low(k, atom_bond_list, molname, id_molname)
172 END SUBROUTINE generate_molname_low
183 LOGICAL,
INTENT(in),
OPTIONAL :: qmmm
187 CHARACTER(len=*),
PARAMETER :: routinen =
'topology_generate_molecule'
188 INTEGER,
PARAMETER :: nblock = 100
190 INTEGER :: atom_in_kind, atom_in_mol, first, handle, handle2, i, iatm, iatom, iend, ifirst, &
191 ilast, inum, istart, itype, iw, j, jump1, jump2, last, max_mol_num, mol_num, mol_res, &
192 mol_typ, myind, n, natom, nlocl, ntype, resid
193 INTEGER,
DIMENSION(:),
POINTER :: qm_atom_index, wrk1, wrk2
194 LOGICAL :: do_again, found, my_qmmm
203 extension=
".subsysLog")
204 CALL timeset(routinen, handle)
205 NULLIFY (qm_atom_index)
215 IF (
PRESENT(qmmm) .AND.
PRESENT(qmmm_env)) my_qmmm = qmmm
218 IF (
ASSOCIATED(atom_info%map_mol_typ))
DEALLOCATE (atom_info%map_mol_typ)
219 ALLOCATE (atom_info%map_mol_typ(natom))
221 IF (
ASSOCIATED(atom_info%map_mol_num))
DEALLOCATE (atom_info%map_mol_num)
222 ALLOCATE (atom_info%map_mol_num(natom))
224 IF (
ASSOCIATED(atom_info%map_mol_res))
DEALLOCATE (atom_info%map_mol_res)
225 ALLOCATE (atom_info%map_mol_res(natom))
228 atom_info%map_mol_typ(:) = 0
229 atom_info%map_mol_num(:) = -1
230 atom_info%map_mol_res(:) = 1
234 atom_info%map_mol_typ(1) = 1
237 wrk1(1) = atom_info%id_molname(1)
242 atom_info%map_mol_typ(iatom) = ntype
246 IF ((atom_info%id_molname(iatom) == atom_info%id_molname(iatom - 1)) .AND. &
248 atom_info%map_mol_typ(iatom) = atom_info%map_mol_typ(iatom - 1)
249 IF (atom_info%id_resname(iatom) == atom_info%id_resname(iatom - 1))
THEN
250 atom_info%map_mol_res(iatom) = atom_info%map_mol_res(iatom - 1)
253 atom_info%map_mol_res(iatom) = resid
259 IF (atom_info%id_molname(iatom) == wrk1(itype))
THEN
260 atom_info%map_mol_typ(iatom) = itype
265 IF (.NOT. found)
THEN
267 atom_info%map_mol_typ(iatom) = ntype
268 IF (ntype >
SIZE(wrk1))
CALL reallocate(wrk1, 1, 2*
SIZE(wrk1))
269 wrk1(ntype) = atom_info%id_molname(iatom)
272 atom_info%map_mol_res(iatom) = resid
275 IF (atom_info%id_molname(iatom - 1) == atom_info%id_molname(iatom))
THEN
276 atom_info%map_mol_typ(iatom) = ntype
279 atom_info%map_mol_typ(iatom) = ntype
285 IF (iw > 0)
WRITE (iw,
'(/,T2,A)')
"Start of molecule generation"
289 ALLOCATE (atom_bond_list(natom))
291 ALLOCATE (atom_bond_list(i)%array1(0))
294 IF (
ASSOCIATED(conn_info%bond_a)) n =
SIZE(conn_info%bond_a)
296 CALL find_molecule(atom_bond_list, atom_info%map_mol_num, atom_info%id_molname)
298 DEALLOCATE (atom_bond_list(i)%array1)
300 DEALLOCATE (atom_bond_list)
301 IF (iw > 0)
WRITE (iw,
'(/,T2,A)')
"End of molecule generation"
304 IF (iw > 0)
WRITE (iw,
'(/,T2,A)')
"Checking for non-continuous generated molecules"
306 ALLOCATE (wrk1(natom))
307 ALLOCATE (wrk2(natom))
308 wrk1 = atom_info%map_mol_num
310 IF (debug_this_module)
THEN
312 WRITE (*,
'(2I10)') i, atom_info%map_mol_num(i)
316 CALL sort(wrk1, natom, wrk2)
318 mol_typ = wrk1(istart)
320 IF (mol_typ /= wrk1(i))
THEN
322 first = minval(wrk2(istart:iend))
323 last = maxval(wrk2(istart:iend))
324 nlocl = last - first + 1
325 IF (iend - istart + 1 /= nlocl)
THEN
326 IF (debug_this_module)
WRITE (*, *) iend, istart, iend - istart + 1, first, last, nlocl
327 CALL cp_abort(__location__, &
328 "CP2K requires molecules to be contiguous and we have detected a non contiguous one!! "// &
329 "In particular a molecule defined from index ("//
cp_to_string(first)//
") to ("// &
330 cp_to_string(last)//
") contains other molecules, not connected! "// &
331 "Too late at this stage everything should be already ordered! "// &
332 "If you have not yet employed the REORDERING keyword, please do so. "// &
333 "It may help to fix this issue.")
336 mol_typ = wrk1(istart)
340 first = minval(wrk2(istart:iend))
341 last = maxval(wrk2(istart:iend))
342 nlocl = last - first + 1
343 IF (iend - istart + 1 /= nlocl)
THEN
344 IF (debug_this_module)
WRITE (*, *) iend, istart, iend - istart + 1, first, last, nlocl
345 CALL cp_abort(__location__, &
346 "CP2K requires molecules to be contiguous and we have detected a non contiguous one!! "// &
347 "In particular a molecule defined from index ("//
cp_to_string(first)//
") to ("// &
348 cp_to_string(last)//
") contains other molecules, not connected! "// &
349 "Too late at this stage everything should be already ordered! "// &
350 "If you have not yet employed the REORDERING keyword, please do so. "// &
351 "It may help to fix this issue.")
355 IF (iw > 0)
WRITE (iw,
'(/,T2,A)')
"End of check"
357 IF (iw > 0)
WRITE (unit=iw, fmt=
"(/,T2,A)")
"Start of renumbering molecules"
360 atom_info%map_mol_num(1) = 1
362 IF (atom_info%id_molname(iatom) /= atom_info%id_molname(iatom - 1))
THEN
364 ELSE IF (atom_info%map_mol_res(iatom) /= atom_info%map_mol_res(iatom - 1))
THEN
365 mol_num = mol_num + 1
367 atom_info%map_mol_num(iatom) = mol_num
370 mol_typ = atom_info%map_mol_typ(1)
371 mol_num = atom_info%map_mol_num(1)
373 IF (atom_info%map_mol_typ(i) /= mol_typ)
THEN
374 myind = atom_info%map_mol_num(i) - mol_num + 1
375 cpassert(myind /= atom_info%map_mol_num(i - 1))
376 mol_typ = atom_info%map_mol_typ(i)
377 mol_num = atom_info%map_mol_num(i)
379 atom_info%map_mol_num(i) = atom_info%map_mol_num(i) - mol_num + 1
382 IF (iw > 0)
WRITE (unit=iw, fmt=
"(/,T2,A)")
"End of renumbering molecules"
385 CALL timeset(routinen//
"_PARA_RES", handle2)
386 IF (iw > 0)
WRITE (unit=iw, fmt=
"(/,T2,A,L2)")
"Starting PARA_RES: ",
topology%para_res
389 atom_info%id_molname(:) = atom_info%id_resname(:)
391 atom_info%map_mol_typ(1) = 1
393 atom_info%map_mol_num(1) = 1
395 IF (atom_info%id_molname(iatom) /= atom_info%id_molname(iatom - 1))
THEN
398 ELSE IF (atom_info%map_mol_res(iatom) /= atom_info%map_mol_res(iatom - 1))
THEN
399 mol_num = mol_num + 1
401 atom_info%map_mol_typ(iatom) = ntype
402 atom_info%map_mol_num(iatom) = mol_num
406 mol_typ = atom_info%map_mol_typ(1)
407 mol_num = atom_info%map_mol_num(1)
408 atom_info%map_mol_res(1) = mol_res
410 IF ((atom_info%resid(i - 1) /= atom_info%resid(i)) .OR. &
411 (atom_info%id_resname(i - 1) /= atom_info%id_resname(i)))
THEN
412 mol_res = mol_res + 1
414 IF ((atom_info%map_mol_typ(i) /= mol_typ) .OR. &
415 (atom_info%map_mol_num(i) /= mol_num))
THEN
416 mol_typ = atom_info%map_mol_typ(i)
417 mol_num = atom_info%map_mol_num(i)
420 atom_info%map_mol_res(i) = mol_res
424 IF (iw > 0)
WRITE (unit=iw, fmt=
"(/,T2,A)")
"End of PARA_RES"
425 CALL timestop(handle2)
429 WRITE (iw,
'(4(1X,A,":",I0),2(1X,A,1X,A))')
"iatom", iatom, &
430 "map_mol_typ", atom_info%map_mol_typ(iatom), &
431 "map_mol_num", atom_info%map_mol_num(iatom), &
432 "map_mol_res", atom_info%map_mol_res(iatom), &
433 "mol_name:", trim(
id2str(atom_info%id_molname(iatom))), &
434 "res_name:", trim(
id2str(atom_info%id_resname(iatom)))
440 IF (iw > 0)
WRITE (iw, *)
"MAP_MOL_NUM ", atom_info%map_mol_num
441 IF (iw > 0)
WRITE (iw, *)
"MAP_MOL_TYP ", atom_info%map_mol_typ
442 IF (iw > 0)
WRITE (iw, *)
"MAP_MOL_RES ", atom_info%map_mol_res
443 ALLOCATE (qm_atom_index(
SIZE(qmmm_env%qm_atom_index)))
444 qm_atom_index = qmmm_env%qm_atom_index
445 cpassert(all(qm_atom_index /= 0))
446 DO myind = 1,
SIZE(qm_atom_index)
447 IF (qm_atom_index(myind) == 0) cycle
448 CALL find_boundary(atom_info%map_mol_typ, natom, ifirst, ilast, &
449 atom_info%map_mol_typ(qm_atom_index(myind)))
450 CALL find_boundary(atom_info%map_mol_typ, atom_info%map_mol_num, natom, ifirst, ilast, &
451 atom_info%map_mol_typ(qm_atom_index(myind)), atom_info%map_mol_num(qm_atom_index(myind)))
452 IF (iw > 0)
WRITE (iw, *)
"qm fragment:: ifirst, ilast", ifirst, ilast
453 cpassert(((ifirst /= 0) .OR. (ilast /= natom)))
454 DO iatm = ifirst, ilast
455 atom_info%id_molname(iatm) =
str2id(
s2s(
"_QM_"// &
456 trim(
id2str(atom_info%id_molname(iatm)))))
457 IF (iw > 0)
WRITE (iw, *)
"QM Molecule name :: ",
id2str(atom_info%id_molname(iatm))
458 WHERE (qm_atom_index == iatm) qm_atom_index = 0
460 DO iatm = 1, ifirst - 1
461 IF (any(qm_atom_index == iatm)) do_again = .true.
463 DO iatm = ilast + 1, natom
464 IF (any(qm_atom_index == iatm)) do_again = .true.
466 IF (iw > 0)
WRITE (iw, *)
" Another QM fragment? :: ", do_again
467 IF (ifirst /= 1)
THEN
468 jump1 = atom_info%map_mol_typ(ifirst) - atom_info%map_mol_typ(ifirst - 1)
469 cpassert(jump1 <= 1 .AND. jump1 >= 0)
470 jump1 = abs(jump1 - 1)
474 IF (ilast /= natom)
THEN
475 jump2 = atom_info%map_mol_typ(ilast + 1) - atom_info%map_mol_typ(ilast)
476 cpassert(jump2 <= 1 .AND. jump2 >= 0)
477 jump2 = abs(jump2 - 1)
483 DO iatm = ifirst, natom
484 atom_info%map_mol_typ(iatm) = atom_info%map_mol_typ(iatm) + jump1
486 DO iatm = ilast + 1, natom
487 atom_info%map_mol_typ(iatm) = atom_info%map_mol_typ(iatm) + jump2
490 DO iatm = ifirst, ilast
491 atom_info%map_mol_num(iatm) = 1
496 CALL find_boundary(atom_info%map_mol_typ, natom, first, last, atom_info%map_mol_typ(ilast + 1))
497 CALL find_boundary(atom_info%map_mol_typ, atom_info%map_mol_num, natom, ifirst, ilast, &
498 atom_info%map_mol_typ(ilast + 1), atom_info%map_mol_num(ilast + 1))
499 atom_in_mol = ilast - ifirst + 1
501 DO iatm = first, last, atom_in_mol
502 atom_info%map_mol_num(iatm:iatm + atom_in_mol - 1) = inum
507 IF (.NOT. do_again)
EXIT
509 DEALLOCATE (qm_atom_index)
512 WRITE (iw, *)
"After the QM/MM Setup:"
514 WRITE (iw, *)
" iatom,map_mol_typ,map_mol_num ", iatom, &
515 atom_info%map_mol_typ(iatom), atom_info%map_mol_num(iatom)
523 WRITE (iw, *)
"SUMMARY:: Number of molecule kinds found:", ntype
524 ntype = maxval(atom_info%map_mol_typ)
526 atom_in_kind = count(atom_info%map_mol_typ == i)
527 WRITE (iw, *)
"Molecule kind:", i,
" contains", atom_in_kind,
" atoms"
528 IF (atom_in_kind <= 1) cycle
529 CALL find_boundary(atom_info%map_mol_typ, natom, first, last, i)
530 WRITE (iw, *)
"Boundary atoms:", first, last
531 cpassert(last - first + 1 == atom_in_kind)
532 max_mol_num = maxval(atom_info%map_mol_num(first:last))
533 WRITE (iw, *)
"Number of molecules of kind", i,
"is ::", max_mol_num
534 atom_in_mol = atom_in_kind/max_mol_num
535 WRITE (iw, *)
"Number of atoms per each molecule:", atom_in_mol
536 WRITE (iw, *)
"MAP_MOL_TYP::", atom_info%map_mol_typ(first:last)
537 WRITE (iw, *)
"MAP_MOL_NUM::", atom_info%map_mol_num(first:last)
538 WRITE (iw, *)
"MAP_MOL_RES::", atom_info%map_mol_res(first:last)
540 DO j = 1, max_mol_num
541 IF (count(atom_info%map_mol_num(first:last) == j) /= atom_in_mol)
THEN
542 WRITE (iw, *)
"molecule type:", i,
"molecule num:", j,
" has ", &
543 count(atom_info%map_mol_num(first:last) == j), &
544 " atoms instead of ", atom_in_mol,
" ."
545 CALL cp_abort(__location__, &
546 "Two molecules of the same kind have "// &
547 "been created with different numbers of atoms!")
553 "PRINT%TOPOLOGY_INFO/UTIL_INFO")
554 CALL timestop(handle)
569 CHARACTER(len=*),
PARAMETER :: routinen =
'topology_generate_bond'
571 CHARACTER(LEN=2) :: upper_sym_1
572 INTEGER :: cbond, handle, handle2, i, iatm1, iatm2, iatom, ibond, idim, iw, j, jatom, k, &
573 n_bonds, n_heavy_bonds, n_hydr_bonds, n_rep, natom, npairs, output_unit
574 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: bond_a, bond_b,
list, map_nb
575 INTEGER,
DIMENSION(:),
POINTER :: isolated_atoms, tmp_v
576 LOGICAL :: connectivity_ok, explicit, print_info
577 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: h_list
578 REAL(kind=
dp) :: bondparm_factor, cell_v(3), dr(3), &
579 ksign, my_maxrad, r2, r2_min, rbond, &
581 REAL(kind=
dp),
DIMENSION(1, 1) :: r_max, r_minsq
582 REAL(kind=
dp),
DIMENSION(:),
POINTER :: radius
583 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: pbc_coord
595 NULLIFY (logger, particle_set, atomic_kind_set, nonbonded, bond_section, generate_section)
596 NULLIFY (isolated_atoms, tmp_v)
597 CALL timeset(routinen, handle)
601 extension=
".subsysLog")
603 ALLOCATE (isolated_atoms(0))
611 CALL reallocate(isolated_atoms, 1,
SIZE(isolated_atoms) +
SIZE(tmp_v))
612 isolated_atoms(
SIZE(isolated_atoms) -
SIZE(tmp_v) + 1:
SIZE(isolated_atoms)) = tmp_v
617 bondparm_factor =
topology%bondparm_factor
622 ALLOCATE (radius(natom))
623 ALLOCATE (
list(natom))
624 ALLOCATE (h_list(natom))
625 ALLOCATE (pbc_coord(3, natom))
627 CALL timeset(trim(routinen)//
"_1", handle2)
630 upper_sym_1 = trim(
id2str(atom_info%id_element(iatom)))
632 CALL get_ptable_info(symbol=upper_sym_1, covalent_radius=radius(iatom))
636 cpabort(
"Illegal bondparm_type")
638 IF (upper_sym_1 ==
"H ") h_list(iatom) = .true.
640 IF (any(isolated_atoms == iatom)) radius(iatom) = 0.0_dp
642 IF (iw > 0)
WRITE (iw,
'(T2,"GENERATE|",5X,A,T50,A5,T60,A,T69,F12.6)') &
643 "In topology_generate_bond :: iatom = ", upper_sym_1, &
644 "radius:", radius(iatom)
646 CALL timestop(handle2)
647 CALL timeset(trim(routinen)//
"_2", handle2)
650 ALLOCATE (atomic_kind_set(1))
653 my_maxrad = maxval(radius)*2.0_dp
654 atomic_kind => atomic_kind_set(1)
656 name=
"XXX", element_symbol=
"XXX", mass=0.0_dp, atom_list=
list)
659 IF (my_maxrad*bondparm_factor > r_max(1, 1) .AND. (.NOT.
topology%molname_generated))
THEN
660 IF (output_unit > 0)
THEN
661 WRITE (output_unit,
'(T2,"GENERATE|",A)') &
662 " ERROR in connectivity generation!", &
663 " The THRESHOLD to select possible bonds is larger than the max. bondlength", &
664 " used to build the neighbors lists. Increase the BONDLENGTH_MAX parameter"
665 WRITE (output_unit,
'(T2,"GENERATE|",2(A,F11.6),A)') &
666 " Present THRESHOLD (", my_maxrad*bondparm_factor,
" )."// &
667 " Present BONDLENGTH_MAX (", r_max(1, 1),
" )"
669 cpabort(
"Unable to generate connectivity")
672 particle_set(i)%atomic_kind => atomic_kind_set(1)
673 particle_set(i)%r(1) = atom_info%r(1, i)
674 particle_set(i)%r(2) = atom_info%r(2, i)
675 particle_set(i)%r(3) = atom_info%r(3, i)
676 pbc_coord(:, i) =
pbc(atom_info%r(:, i),
topology%cell)
680 CALL timestop(handle2)
681 CALL timeset(trim(routinen)//
"_3", handle2)
683 cell=
topology%cell, r_max=r_max, r_minsq=r_minsq, &
684 ei_scale14=1.0_dp, vdw_scale14=1.0_dp, nonbonded=nonbonded, &
685 para_env=para_env, build_from_scratch=.true., geo_check=.true., &
686 mm_section=generate_section)
688 WRITE (iw,
'(T2,"GENERATE| Number of prescreened bonds (neighbors):",T71,I10)') &
689 nonbonded%neighbor_kind_pairs(1)%npairs
692 DO i = 1,
SIZE(nonbonded%neighbor_kind_pairs)
693 npairs = npairs + nonbonded%neighbor_kind_pairs(i)%npairs
695 ALLOCATE (bond_a(npairs))
696 ALLOCATE (bond_b(npairs))
697 ALLOCATE (map_nb(npairs))
699 DO j = 1,
SIZE(nonbonded%neighbor_kind_pairs)
700 DO i = 1, nonbonded%neighbor_kind_pairs(j)%npairs
702 bond_a(idim) = nonbonded%neighbor_kind_pairs(j)%list(1, i)
703 bond_b(idim) = nonbonded%neighbor_kind_pairs(j)%list(2, i)
707 CALL timestop(handle2)
708 CALL timeset(trim(routinen)//
"_4", handle2)
710 ALLOCATE (bond_list(natom))
712 ALLOCATE (bond_list(i)%array1(0))
713 ALLOCATE (bond_list(i)%array2(0))
724 connectivity_ok = .false.
728 atom_info%id_molname =
str2id(
s2s(
"TO_DEFINE_LATER"))
734 DO WHILE (.NOT. connectivity_ok)
738 IF (h_list(iatm1)) cycle
739 DO j = 1,
SIZE(bond_list(iatm1)%array1)
740 iatm2 = bond_list(iatm1)%array1(j)
741 IF (atom_info%id_molname(iatm1) /= atom_info%id_molname(iatm2)) cycle
742 IF (h_list(iatm2) .OR. (iatm2 <= iatm1)) cycle
743 k = bond_list(iatm1)%array2(j)
744 ksign = sign(1.0_dp, real(k, kind=
dp))
746 cell_v = matmul(
topology%cell%hmat, &
747 REAL(nonbonded%neighbor_kind_pairs(k)%cell_vector, kind=
dp))
748 dr = pbc_coord(:, iatm1) - pbc_coord(:, iatm2) - ksign*cell_v
749 r2 = dot_product(dr, dr)
750 IF (r2 <= r_minsq(1, 1))
THEN
751 CALL cp_abort(__location__, &
752 "bond distance between atoms less then the smallest distance provided "// &
756 IF ((any(isolated_atoms == iatm1)) .OR. (any(isolated_atoms == iatm2))) cycle
760 rbond = radius(iatm1) + radius(iatm2)
762 rbond = max(radius(iatm1), radius(iatm2))
765 rbond2 = rbond2*(bondparm_factor)**2
767 IF (r2 <= rbond2)
THEN
768 n_heavy_bonds = n_heavy_bonds + 1
769 CALL add_bonds_list(conn_info, iatm1, iatm2, n_heavy_bonds)
774 n_bonds = n_heavy_bonds
777 IF (output_unit > 0)
WRITE (output_unit, *)
779 IF (.NOT. h_list(iatm1)) cycle
780 r2_min = huge(0.0_dp)
783 DO j = 1,
SIZE(bond_list(iatm1)%array1)
784 iatm2 = bond_list(iatm1)%array1(j)
786 IF (atom_info%id_molname(iatm1) /= atom_info%id_molname(iatm2)) cycle
787 IF (h_list(iatm2) .AND. (iatm2 <= iatm1)) cycle
789 IF ((any(isolated_atoms == iatm1)) .OR. (any(isolated_atoms == iatm2))) cycle
791 k = bond_list(iatm1)%array2(j)
792 ksign = sign(1.0_dp, real(k, kind=
dp))
794 cell_v = matmul(
topology%cell%hmat, &
795 REAL(nonbonded%neighbor_kind_pairs(k)%cell_vector, kind=
dp))
796 dr = pbc_coord(:, iatm1) - pbc_coord(:, iatm2) - ksign*cell_v
797 r2 = dot_product(dr, dr)
798 IF (r2 <= r_minsq(1, 1))
THEN
799 CALL cp_abort(__location__, &
800 "bond distance between atoms less then the smallest distance provided "// &
803 IF (r2 <= r2_min)
THEN
808 IF (ibond == -1)
THEN
809 IF (output_unit > 0 .AND. print_info)
THEN
810 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,I10,A)') &
811 "WARNING:: No connections detected for Hydrogen - Atom Nr:", iatm1,
" !"
814 n_hydr_bonds = n_hydr_bonds + 1
815 n_bonds = n_bonds + 1
816 CALL add_bonds_list(conn_info, min(iatm1, ibond), max(iatm1, ibond), n_bonds)
819 IF (output_unit > 0)
THEN
820 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)') &
821 " Preliminary Number of Bonds generated:", n_bonds
825 CALL connectivity_external_control(section=bond_section, &
826 iarray1=conn_info%bond_a, &
827 iarray2=conn_info%bond_b, &
830 output_unit=output_unit)
837 IF (.NOT.
topology%reorder_atom)
THEN
839 IF (output_unit > 0)
WRITE (output_unit,
'(T2,"GENERATE|",A)') &
840 " Molecules names have been generated. Now reordering particle set in order to have ", &
841 " atoms belonging to the same molecule in a sequential order."
843 connectivity_ok = .true.
846 connectivity_ok = check_generate_mol(conn_info%bond_a, conn_info%bond_b, &
847 atom_info, bondparm_factor, output_unit)
849 IF (my_maxrad*bondparm_factor > r_max(1, 1) .AND. (.NOT.
topology%molname_generated))
THEN
850 IF (output_unit > 0)
THEN
851 WRITE (output_unit,
'(T2,"GENERATE|",A)') &
852 " ERROR in connectivity generation!", &
853 " The THRESHOLD to select possible bonds is bigger than the MAX bondlength", &
854 " used to build the neighbors lists. Increase the BONDLENGTH_MAX patameter"
855 WRITE (output_unit,
'(T2,"GENERATE|",2(A,F11.6),A)') &
856 " Present THRESHOLD (", my_maxrad*bondparm_factor,
" )."// &
857 " Present BONDLENGTH_MAX (", r_max(1, 1),
" )"
859 cpabort(
"Unable to generate connectivity")
862 IF (connectivity_ok .AND. (output_unit > 0))
THEN
863 WRITE (output_unit,
'(T2,"GENERATE|",A)') &
864 " Achieved consistency in connectivity generation."
867 CALL timestop(handle2)
868 CALL timeset(trim(routinen)//
"_6", handle2)
871 DEALLOCATE (bond_list(i)%array1)
872 DEALLOCATE (bond_list(i)%array2)
874 DEALLOCATE (bond_list)
875 DEALLOCATE (pbc_coord)
881 CALL timestop(handle2)
882 IF (output_unit > 0 .AND. n_bonds > 0)
THEN
883 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Number of Bonds generated:", &
886 CALL timeset(trim(routinen)//
"_7", handle2)
891 DO ibond = 1,
SIZE(conn_info%bond_a)
892 iatom = conn_info%bond_a(ibond)
893 jatom = conn_info%bond_b(ibond)
894 IF ((atom_info%id_molname(iatom) /= atom_info%id_molname(jatom)) .OR. &
895 (atom_info%resid(iatom) /= atom_info%resid(jatom)) .OR. &
896 (atom_info%id_resname(iatom) /= atom_info%id_resname(jatom)))
THEN
897 IF (iw > 0)
WRITE (iw, *)
" PARA_RES, bond between molecules atom ", &
902 conn_info%c_bond_a(cbond) = iatom
903 conn_info%c_bond_b(cbond) = jatom
905 IF (atom_info%id_molname(iatom) /= atom_info%id_molname(jatom))
THEN
906 cpabort(
"Bonds between different molecule types?")
911 CALL timestop(handle2)
912 DEALLOCATE (isolated_atoms)
913 CALL timestop(handle)
915 "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
928 FUNCTION check_generate_mol(bond_a, bond_b, atom_info, bondparm_factor, output_unit) &
930 INTEGER,
DIMENSION(:),
POINTER :: bond_a, bond_b
932 REAL(kind=
dp),
INTENT(INOUT) :: bondparm_factor
933 INTEGER,
INTENT(IN) :: output_unit
936 CHARACTER(len=*),
PARAMETER :: routinen =
'check_generate_mol'
938 CHARACTER(LEN=10) :: ctmp1, ctmp2, ctmp3
939 INTEGER :: handle, i, idim, itype, j, mol_natom, &
941 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: mol_info_tmp
942 INTEGER,
DIMENSION(:),
POINTER :: mol_map, mol_map_o, wrk
943 INTEGER,
DIMENSION(:, :),
POINTER :: mol_info
944 LOGICAL,
DIMENSION(:),
POINTER :: icheck
947 CALL timeset(routinen, handle)
949 natom =
SIZE(atom_info%id_atmname)
950 ALLOCATE (bond_list(natom))
952 ALLOCATE (bond_list(i)%array1(0))
955 ALLOCATE (mol_map(natom))
956 ALLOCATE (mol_map_o(natom))
957 ALLOCATE (wrk(natom))
960 mol_map(i) = atom_info%id_molname(i)
964 CALL sort(mol_map, natom, wrk)
978 ALLOCATE (mol_info_tmp(natom, 2))
983 mol_info_tmp(1, 1) = itype
985 IF (mol_map(i) /= itype)
THEN
988 mol_info_tmp(nsize, 1) = itype
989 mol_info_tmp(nsize - 1, 2) = idim
995 mol_info_tmp(nsize, 2) = idim
997 ALLOCATE (mol_info(nsize, 4))
998 mol_info(1:nsize, 1:2) = mol_info_tmp(1:nsize, 1:2)
999 DEALLOCATE (mol_info_tmp)
1006 ALLOCATE (icheck(natom))
1009 IF (icheck(i)) cycle
1010 itype = mol_map_o(i)
1013 DO j = 1,
SIZE(mol_info)
1014 IF (itype == mol_info(j, 1))
EXIT
1016 mol_info(j, 3) = mol_info(j, 3) + 1
1017 IF (mol_info(j, 4) == 0) mol_info(j, 4) = mol_natom
1018 IF (mol_info(j, 4) /= mol_natom)
THEN
1024 bondparm_factor = bondparm_factor*1.05_dp
1025 IF (output_unit < 0)
EXIT
1026 WRITE (output_unit,
'(/,T2,"GENERATE|",A)')
" WARNING in connectivity generation!"
1027 WRITE (output_unit,
'(T2,"GENERATE|",A)') &
1028 ' Two molecules/residues named ('//trim(
id2str(itype))//
') have different '// &
1033 WRITE (output_unit,
'(T2,"GENERATE|",A)')
' Molecule starting at position ('// &
1034 trim(ctmp1)//
') has Nr. <'//trim(ctmp2)// &
1035 '> of atoms.',
' while the other same molecules have Nr. <'// &
1036 trim(ctmp3)//
'> of atoms!'
1037 WRITE (output_unit,
'(T2,"GENERATE|",A)') &
1038 ' Increasing bondparm_factor by 1.05.. An error was found in the generated', &
1039 ' connectivity. Retry...'
1040 WRITE (output_unit,
'(T2,"GENERATE|",A,F11.6,A,/)') &
1041 " Present value of BONDPARM_FACTOR (", bondparm_factor,
" )."
1047 DEALLOCATE (mol_info)
1048 DEALLOCATE (mol_map)
1049 DEALLOCATE (mol_map_o)
1052 DEALLOCATE (bond_list(i)%array1)
1054 DEALLOCATE (bond_list)
1055 CALL timestop(handle)
1056 END FUNCTION check_generate_mol
1072 SUBROUTINE connectivity_external_control(section, Iarray1, Iarray2, Iarray3, Iarray4, nvar, &
1073 topology, output_unit, is_impr)
1075 INTEGER,
DIMENSION(:),
POINTER :: iarray1, iarray2
1076 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: iarray3, iarray4
1077 INTEGER,
INTENT(INOUT) :: nvar
1079 INTEGER,
INTENT(IN) :: output_unit
1080 LOGICAL,
INTENT(IN),
OPTIONAL :: is_impr
1082 CHARACTER(LEN=8) :: fmt
1083 INTEGER :: do_action, do_it, i, j, k, n_rep, &
1084 n_rep_val, natom, new_size, nsize
1085 INTEGER,
DIMENSION(:),
POINTER :: atlist, ilist1, ilist2, ilist3, ilist4
1086 LOGICAL :: explicit, ip3, ip4
1090 ip3 =
PRESENT(iarray3)
1091 ip4 =
PRESENT(iarray4)
1093 IF (ip3) nsize = nsize + 1
1094 IF (ip3 .AND. ip4) nsize = nsize + 1
1100 NULLIFY (ilist1, ilist2, ilist3, ilist4, atlist)
1101 ALLOCATE (ilist1(nvar))
1102 ALLOCATE (ilist2(nvar))
1103 ilist1 = iarray1(1:nvar)
1104 ilist2 = iarray2(1:nvar)
1108 ALLOCATE (ilist3(nvar))
1109 ilist3 = iarray3(1:nvar)
1111 ALLOCATE (ilist3(nvar))
1112 ALLOCATE (ilist4(nvar))
1113 ilist3 = iarray3(1:nvar)
1114 ilist4 = iarray4(1:nvar)
1117 cpabort(
"Only 2, 3, 4 are supported as the value of nsize")
1119 CALL list_canonical_order(ilist1, ilist2, ilist3, ilist4, nsize, is_impr)
1129 cpassert(
SIZE(atlist) == nsize)
1131 CALL check_element_list(do_it, do_action, atlist, ilist1, ilist2, ilist3, ilist4, &
1133 IF (do_action ==
do_add)
THEN
1137 IF (output_unit > 0)
THEN
1138 WRITE (output_unit,
'(T2,"ADD|",1X,A,I6,'//trim(fmt)//
'(A,I6),A,T64,A,I6)') &
1140 atlist(1), (
",", atlist(k), k=2, nsize),
") added.",
" NEW size::", nvar
1142 IF (nvar >
SIZE(iarray1))
THEN
1143 new_size = int(5 + 1.2*nvar)
1155 iarray1(do_it + 1:nvar) = iarray1(do_it:nvar - 1)
1156 iarray2(do_it + 1:nvar) = iarray2(do_it:nvar - 1)
1157 iarray1(do_it) = ilist1(do_it)
1158 iarray2(do_it) = ilist2(do_it)
1161 iarray3(do_it + 1:nvar) = iarray3(do_it:nvar - 1)
1162 iarray3(do_it) = ilist3(do_it)
1164 iarray3(do_it + 1:nvar) = iarray3(do_it:nvar - 1)
1165 iarray4(do_it + 1:nvar) = iarray4(do_it:nvar - 1)
1166 iarray3(do_it) = ilist3(do_it)
1167 iarray4(do_it) = ilist4(do_it)
1170 IF (output_unit > 0)
THEN
1171 WRITE (output_unit,
'(T2,"ADD|",1X,A,I6,'//trim(fmt)//
'(A,I6),A,T80,A)') &
1173 atlist(1), (
",", atlist(k), k=2, nsize),
") already found.",
"X"
1180 IF (output_unit > 0)
THEN
1181 WRITE (output_unit,
'(T2,"RMV|",1X,A,I6,'//trim(fmt)//
'(A,I6),A,T64,A,I6)') &
1183 atlist(1), (
",", atlist(k), k=2, nsize),
") removed.",
" NEW size::", nvar
1185 iarray1(do_it:nvar) = iarray1(do_it + 1:nvar + 1)
1186 iarray2(do_it:nvar) = iarray2(do_it + 1:nvar + 1)
1187 iarray1(nvar + 1) = -huge(0)
1188 iarray2(nvar + 1) = -huge(0)
1191 iarray3(do_it:nvar) = iarray3(do_it + 1:nvar + 1)
1192 iarray3(nvar + 1) = -huge(0)
1194 iarray3(do_it:nvar) = iarray3(do_it + 1:nvar + 1)
1195 iarray4(do_it:nvar) = iarray4(do_it + 1:nvar + 1)
1196 iarray3(nvar + 1) = -huge(0)
1197 iarray4(nvar + 1) = -huge(0)
1200 IF (output_unit > 0)
THEN
1201 WRITE (output_unit,
'(T2,"RMV|",1X,A,I6,'//trim(fmt)//
'(A,I6),A,T80,A)') &
1203 atlist(1), (
",", atlist(k), k=2, nsize),
") not found.",
"X"
1221 cpabort(
"Only 2, 3, 4 are supported as the value of nsize")
1224 END SUBROUTINE connectivity_external_control
1237 SUBROUTINE list_canonical_order(Ilist1, Ilist2, Ilist3, Ilist4, nsize, is_impr)
1238 INTEGER,
DIMENSION(:),
POINTER :: ilist1, ilist2
1239 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: ilist3, ilist4
1240 INTEGER,
INTENT(IN) :: nsize
1241 LOGICAL,
INTENT(IN),
OPTIONAL :: is_impr
1243 INTEGER :: i, ss(3), tmp1, tmp2, tmp3, tt(3)
1247 IF (
PRESENT(is_impr)) do_impr = is_impr
1250 DO i = 1,
SIZE(ilist1)
1253 ilist1(i) = min(tmp1, tmp2)
1254 ilist2(i) = max(tmp1, tmp2)
1257 DO i = 1,
SIZE(ilist1)
1260 ilist1(i) = min(tmp1, tmp2)
1261 ilist3(i) = max(tmp1, tmp2)
1264 DO i = 1,
SIZE(ilist1)
1265 IF (.NOT. do_impr)
THEN
1268 ilist1(i) = min(tmp1, tmp2)
1269 IF (ilist1(i) == tmp2)
THEN
1271 ilist3(i) = ilist2(i)
1274 ilist4(i) = max(tmp1, tmp2)
1279 CALL sort(tt, 3, ss)
1287 END SUBROUTINE list_canonical_order
1301 SUBROUTINE check_element_list(do_it, do_action, atlist, Ilist1, Ilist2, Ilist3, Ilist4, &
1303 INTEGER,
INTENT(OUT) :: do_it
1304 INTEGER,
INTENT(IN) :: do_action
1305 INTEGER,
DIMENSION(:),
POINTER :: atlist, ilist1, ilist2
1306 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: ilist3, ilist4
1307 LOGICAL,
INTENT(IN),
OPTIONAL :: is_impr
1309 INTEGER :: i, iend, istart, ndim, new_size, nsize, &
1310 ss(3), tmp1, tmp2, tmp3, tt(3)
1311 INTEGER,
DIMENSION(4) :: tmp
1312 LOGICAL :: do_impr, found
1315 IF (
PRESENT(is_impr)) do_impr = is_impr
1317 nsize =
SIZE(atlist)
1326 tmp(1) = min(tmp1, tmp2)
1327 tmp(2) = max(tmp1, tmp2)
1331 tmp(1) = min(tmp1, tmp2)
1332 tmp(3) = max(tmp1, tmp2)
1334 IF (.NOT. do_impr)
THEN
1337 tmp(1) = min(tmp1, tmp2)
1338 IF (tmp(1) == tmp2)
THEN
1343 tmp(4) = max(tmp1, tmp2)
1348 CALL sort(tt, 3, ss)
1356 IF (ilist1(istart) >= tmp(1))
EXIT
1359 IF (istart <= ndim)
THEN
1360 IF (ilist1(istart) > tmp(1) .AND. (istart /= 1)) istart = istart - 1
1362 DO iend = istart, ndim
1363 IF (ilist1(iend) /= tmp(1))
EXIT
1365 IF (iend == ndim + 1) iend = ndim
1370 IF ((ilist1(i) > tmp(1)) .OR. (ilist2(i) > tmp(2)))
EXIT
1371 IF ((ilist1(i) == tmp(1)) .AND. (ilist2(i) == tmp(2)))
THEN
1378 IF ((ilist1(i) > tmp(1)) .OR. (ilist2(i) > tmp(2)) .OR. (ilist3(i) > tmp(3)))
EXIT
1379 IF ((ilist1(i) == tmp(1)) .AND. (ilist2(i) == tmp(2)) .AND. (ilist3(i) == tmp(3)))
THEN
1386 IF ((ilist1(i) > tmp(1)) .OR. (ilist2(i) > tmp(2)) .OR. (ilist3(i) > tmp(3)) .OR. (ilist4(i) > tmp(4)))
EXIT
1387 IF ((ilist1(i) == tmp(1)) .AND. (ilist2(i) == tmp(2)) &
1388 .AND. (ilist3(i) == tmp(3)) .AND. (ilist4(i) == tmp(4)))
THEN
1394 SELECT CASE (do_action)
1411 ilist1(i + 1:new_size) = ilist1(i:ndim)
1412 ilist2(i + 1:new_size) = ilist2(i:ndim)
1418 ilist3(i + 1:new_size) = ilist3(i:ndim)
1423 ilist3(i + 1:new_size) = ilist3(i:ndim)
1424 ilist4(i + 1:new_size) = ilist4(i:ndim)
1434 ilist1(i:new_size) = ilist1(i + 1:ndim)
1435 ilist2(i:new_size) = ilist2(i + 1:ndim)
1440 ilist3(i:new_size) = ilist3(i + 1:ndim)
1443 ilist3(i:new_size) = ilist3(i + 1:ndim)
1444 ilist4(i:new_size) = ilist4(i + 1:ndim)
1455 END SUBROUTINE check_element_list
1465 SUBROUTINE add_bonds_list(conn_info, atm1, atm2, n_bonds)
1467 INTEGER,
INTENT(IN) :: atm1, atm2, n_bonds
1469 INTEGER :: new_size, old_size
1471 old_size =
SIZE(conn_info%bond_a)
1472 IF (n_bonds > old_size)
THEN
1473 new_size = int(5 + 1.2*old_size)
1474 CALL reallocate(conn_info%bond_a, 1, new_size)
1475 CALL reallocate(conn_info%bond_b, 1, new_size)
1477 conn_info%bond_a(n_bonds) = atm1
1478 conn_info%bond_b(n_bonds) = atm2
1479 END SUBROUTINE add_bonds_list
1491 CHARACTER(len=*),
PARAMETER :: routinen =
'topology_generate_bend'
1493 INTEGER :: handle, handle2, i, iw, natom, nbond, &
1494 nsize, ntheta, output_unit
1503 extension=
".subsysLog")
1504 CALL timeset(routinen, handle)
1511 IF (
ASSOCIATED(conn_info%bond_a))
THEN
1512 nbond =
SIZE(conn_info%bond_a)
1517 IF (nbond /= 0)
THEN
1518 nsize = int(5 + 1.2*ntheta)
1523 ALLOCATE (bond_list(natom))
1525 ALLOCATE (bond_list(i)%array1(0))
1529 CALL timeset(routinen//
"_1", handle2)
1530 CALL match_iterative_path(iarray1=bond_list, &
1531 iarray2=bond_list, &
1534 oarray1=conn_info%theta_a, &
1535 oarray2=conn_info%theta_b, &
1536 oarray3=conn_info%theta_c)
1537 CALL timestop(handle2)
1539 DEALLOCATE (bond_list(i)%array1)
1541 DEALLOCATE (bond_list)
1542 IF (output_unit > 0)
THEN
1543 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Preliminary Number of Bends generated:", &
1548 CALL connectivity_external_control(section=bend_section, &
1549 iarray1=conn_info%theta_a, &
1550 iarray2=conn_info%theta_b, &
1551 iarray3=conn_info%theta_c, &
1554 output_unit=output_unit)
1557 CALL reallocate(conn_info%theta_a, 1, ntheta)
1558 CALL reallocate(conn_info%theta_b, 1, ntheta)
1559 CALL reallocate(conn_info%theta_c, 1, ntheta)
1560 IF (output_unit > 0 .AND. ntheta > 0)
THEN
1561 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Number of Bends generated:", &
1564 CALL timestop(handle)
1566 "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
1586 RECURSIVE SUBROUTINE match_iterative_path(Iarray1, Iarray2, Iarray3, &
1587 max_levl, Oarray1, Oarray2, Oarray3, Oarray4, Ilist, it_levl, nvar)
1590 POINTER :: iarray2, iarray3
1591 INTEGER,
INTENT(IN) :: max_levl
1592 INTEGER,
DIMENSION(:),
POINTER :: oarray1, oarray2
1593 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: oarray3, oarray4
1594 INTEGER,
DIMENSION(:),
INTENT(INOUT),
OPTIONAL :: ilist
1595 INTEGER,
INTENT(IN),
OPTIONAL :: it_levl
1596 INTEGER,
INTENT(INOUT) :: nvar
1598 INTEGER :: i, ind, j, my_levl, natom
1599 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: my_list
1603 check = max_levl >= 2 .AND. max_levl <= 4
1605 IF (.NOT.
PRESENT(ilist))
THEN
1606 SELECT CASE (max_levl)
1608 cpassert(.NOT.
PRESENT(iarray2))
1609 cpassert(.NOT.
PRESENT(iarray3))
1610 cpassert(.NOT.
PRESENT(oarray3))
1611 cpassert(.NOT.
PRESENT(oarray4))
1613 cpassert(
PRESENT(iarray2))
1614 cpassert(.NOT.
PRESENT(iarray3))
1615 cpassert(
PRESENT(oarray3))
1616 cpassert(.NOT.
PRESENT(oarray4))
1618 cpassert(
PRESENT(iarray2))
1619 cpassert(
PRESENT(iarray3))
1620 cpassert(
PRESENT(oarray3))
1621 cpassert(
PRESENT(oarray4))
1624 natom =
SIZE(iarray1)
1625 IF (.NOT.
PRESENT(ilist))
THEN
1627 ALLOCATE (my_list(max_levl))
1631 my_list(my_levl) = i
1632 CALL match_iterative_path(iarray1=iarray1, &
1635 it_levl=my_levl + 1, &
1636 max_levl=max_levl, &
1644 DEALLOCATE (my_list)
1646 SELECT CASE (it_levl)
1654 i = ilist(it_levl - 1)
1655 DO j = 1,
SIZE(iarray1(i)%array1)
1656 ind = wrk(i)%array1(j)
1657 IF (any(ilist == ind)) cycle
1658 IF (it_levl < max_levl)
THEN
1659 ilist(it_levl) = ind
1660 CALL match_iterative_path(iarray1=iarray1, &
1663 it_levl=it_levl + 1, &
1664 max_levl=max_levl, &
1672 ELSEIF (it_levl == max_levl)
THEN
1673 IF (ilist(1) > ind) cycle
1674 ilist(it_levl) = ind
1676 SELECT CASE (it_levl)
1678 IF (nvar >
SIZE(oarray1))
THEN
1679 CALL reallocate(oarray1, 1, int(5 + 1.2*nvar))
1680 CALL reallocate(oarray2, 1, int(5 + 1.2*nvar))
1682 oarray1(nvar) = ilist(1)
1683 oarray2(nvar) = ilist(2)
1685 IF (nvar >
SIZE(oarray1))
THEN
1686 CALL reallocate(oarray1, 1, int(5 + 1.2*nvar))
1687 CALL reallocate(oarray2, 1, int(5 + 1.2*nvar))
1688 CALL reallocate(oarray3, 1, int(5 + 1.2*nvar))
1690 oarray1(nvar) = ilist(1)
1691 oarray2(nvar) = ilist(2)
1692 oarray3(nvar) = ilist(3)
1694 IF (nvar >
SIZE(oarray1))
THEN
1695 CALL reallocate(oarray1, 1, int(5 + 1.2*nvar))
1696 CALL reallocate(oarray2, 1, int(5 + 1.2*nvar))
1697 CALL reallocate(oarray3, 1, int(5 + 1.2*nvar))
1698 CALL reallocate(oarray4, 1, int(5 + 1.2*nvar))
1700 oarray1(nvar) = ilist(1)
1701 oarray2(nvar) = ilist(2)
1702 oarray3(nvar) = ilist(3)
1703 oarray4(nvar) = ilist(4)
1706 cpabort(
"Only 2, 3, 4 are supported as the value of it_levl")
1711 cpabort(
"it_levl exceeds max_levl in match_iterative_path")
1715 END SUBROUTINE match_iterative_path
1728 CHARACTER(len=*),
PARAMETER :: routinen =
'topology_generate_ub'
1730 INTEGER :: handle, itheta, iw, ntheta, output_unit
1737 extension=
".subsysLog")
1739 CALL timeset(routinen, handle)
1741 ntheta =
SIZE(conn_info%theta_a)
1746 DO itheta = 1, ntheta
1747 conn_info%ub_a(itheta) = conn_info%theta_a(itheta)
1748 conn_info%ub_b(itheta) = conn_info%theta_b(itheta)
1749 conn_info%ub_c(itheta) = conn_info%theta_c(itheta)
1751 IF (output_unit > 0 .AND. ntheta > 0)
THEN
1752 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Number of UB generated:", &
1755 CALL timestop(handle)
1757 "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
1771 CHARACTER(len=*),
PARAMETER :: routinen =
'topology_generate_dihe'
1773 INTEGER :: handle, i, iw, natom, nbond, nphi, &
1783 extension=
".subsysLog")
1785 CALL timeset(routinen, handle)
1788 nbond =
SIZE(conn_info%bond_a)
1789 IF (nbond /= 0)
THEN
1790 nsize = int(5 + 1.2*nphi)
1797 ALLOCATE (bond_list(natom))
1799 ALLOCATE (bond_list(i)%array1(0))
1803 CALL match_iterative_path(iarray1=bond_list, &
1804 iarray2=bond_list, &
1805 iarray3=bond_list, &
1808 oarray1=conn_info%phi_a, &
1809 oarray2=conn_info%phi_b, &
1810 oarray3=conn_info%phi_c, &
1811 oarray4=conn_info%phi_d)
1813 DEALLOCATE (bond_list(i)%array1)
1815 DEALLOCATE (bond_list)
1816 IF (output_unit > 0)
THEN
1817 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Preliminary Number of Torsions generated:", &
1822 CALL connectivity_external_control(section=torsion_section, &
1823 iarray1=conn_info%phi_a, &
1824 iarray2=conn_info%phi_b, &
1825 iarray3=conn_info%phi_c, &
1826 iarray4=conn_info%phi_d, &
1829 output_unit=output_unit)
1836 IF (output_unit > 0 .AND. nphi > 0)
THEN
1837 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Number of Torsions generated:", &
1840 CALL timestop(handle)
1842 "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
1856 CHARACTER(len=*),
PARAMETER :: routinen =
'topology_generate_impr'
1858 CHARACTER(LEN=2) :: atm_symbol
1859 INTEGER :: handle, i, ind, iw, j, natom, nbond, &
1860 nimpr, nsize, output_unit
1861 LOGICAL :: accept_impr
1871 extension=
".subsysLog")
1873 CALL timeset(routinen, handle)
1878 nbond =
SIZE(conn_info%bond_a)
1879 IF (nbond /= 0)
THEN
1880 nsize = int(5 + 1.2*nimpr)
1886 ALLOCATE (bond_list(natom))
1888 ALLOCATE (bond_list(i)%array1(0))
1893 IF (
SIZE(bond_list(i)%array1) == 3)
THEN
1896 accept_impr = .true.
1897 atm_symbol = trim(
id2str(atom_info%id_element(i)))
1899 IF (atm_symbol ==
"N ")
THEN
1900 accept_impr = .false.
1904 ind = bond_list(i)%array1(j)
1905 IF (
SIZE(bond_list(ind)%array1) == 3) accept_impr = .true.
1908 IF (.NOT. accept_impr) cycle
1910 IF (nimpr >
SIZE(conn_info%impr_a))
THEN
1911 nsize = int(5 + 1.2*nimpr)
1917 conn_info%impr_a(nimpr) = i
1918 conn_info%impr_b(nimpr) = bond_list(i)%array1(1)
1919 conn_info%impr_c(nimpr) = bond_list(i)%array1(2)
1920 conn_info%impr_d(nimpr) = bond_list(i)%array1(3)
1924 DEALLOCATE (bond_list(i)%array1)
1926 DEALLOCATE (bond_list)
1929 CALL connectivity_external_control(section=impr_section, &
1930 iarray1=conn_info%impr_a, &
1931 iarray2=conn_info%impr_b, &
1932 iarray3=conn_info%impr_c, &
1933 iarray4=conn_info%impr_d, &
1936 output_unit=output_unit, &
1944 IF (output_unit > 0 .AND. nimpr > 0)
THEN
1945 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Number of Impropers generated:", &
1948 CALL timestop(handle)
1950 "PRINT%TOPOLOGY_INFO/GENERATE_INFO")
1963 CHARACTER(len=*),
PARAMETER :: routinen =
'topology_generate_onfo'
1965 INTEGER :: atom_a, atom_b, handle, i, ionfo, iw, &
1966 natom, nbond, nphi, ntheta, output_unit
1967 TYPE(
array1_list_type),
DIMENSION(:),
POINTER :: bond_list, phi_list, theta_list
1974 extension=
".subsysLog")
1976 CALL timeset(routinen, handle)
1982 ALLOCATE (bond_list(natom))
1984 ALLOCATE (bond_list(i)%array1(0))
1986 nbond =
SIZE(conn_info%bond_a)
1990 ALLOCATE (theta_list(natom))
1992 ALLOCATE (theta_list(i)%array1(0))
1994 ntheta =
SIZE(conn_info%theta_a)
1995 CALL reorder_structure(theta_list, conn_info%theta_a, conn_info%theta_c, ntheta)
1998 ALLOCATE (phi_list(natom))
2000 ALLOCATE (phi_list(i)%array1(0))
2002 nphi =
SIZE(conn_info%phi_a)
2010 DO atom_a = 1, natom
2011 DO i = 1,
SIZE(phi_list(atom_a)%array1)
2012 atom_b = phi_list(atom_a)%array1(i)
2014 IF (atom_a > atom_b) cycle
2016 IF (any(atom_b == bond_list(atom_a)%array1)) cycle
2018 IF (any(atom_b == theta_list(atom_a)%array1)) cycle
2020 IF (any(atom_b == phi_list(atom_a)%array1(:i - 1))) cycle
2022 conn_info%onfo_a(ionfo) = atom_a
2023 conn_info%onfo_b(ionfo) = atom_b
2033 DEALLOCATE (bond_list(i)%array1)
2035 DEALLOCATE (bond_list)
2038 DEALLOCATE (theta_list(i)%array1)
2040 DEALLOCATE (theta_list)
2043 DEALLOCATE (phi_list(i)%array1)
2045 DEALLOCATE (phi_list)
2048 IF (output_unit > 0 .AND. ionfo > 0)
THEN
2049 WRITE (output_unit,
'(T2,"GENERATE|",1X,A,T71,I10)')
" Number of 1-4 interactions generated:", &
2052 CALL timestop(handle)
2054 "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