2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
37 /* This file is completely threadsafe - keep it that way! */
49 #include "gromacs/fileio/confio.h"
50 #include "gromacs/gmxpreprocess/gpp_nextnb.h"
51 #include "gromacs/gmxpreprocess/grompp-impl.h"
52 #include "gromacs/gmxpreprocess/hackblock.h"
53 #include "gromacs/gmxpreprocess/notset.h"
54 #include "gromacs/gmxpreprocess/pgutil.h"
55 #include "gromacs/gmxpreprocess/resall.h"
56 #include "gromacs/gmxpreprocess/topio.h"
57 #include "gromacs/gmxpreprocess/toputil.h"
58 #include "gromacs/math/vec.h"
59 #include "gromacs/topology/ifunc.h"
60 #include "gromacs/utility/cstringutil.h"
61 #include "gromacs/utility/fatalerror.h"
62 #include "gromacs/utility/smalloc.h"
64 #define DIHEDRAL_WAS_SET_IN_RTP 0
65 static bool was_dihedral_set_in_rtp(const t_param *dih)
67 return dih->c[MAXFORCEPARAM-1] == DIHEDRAL_WAS_SET_IN_RTP;
70 typedef bool (*peq)(t_param *p1, t_param *p2);
72 static int acomp(const void *a1, const void *a2)
74 const t_param *p1, *p2;
77 p1 = static_cast<const t_param *>(a1);
78 p2 = static_cast<const t_param *>(a2);
79 if ((ac = (p1->aj()-p2->aj())) != 0)
83 else if ((ac = (p1->ai()-p2->ai())) != 0)
89 return (p1->ak()-p2->ak());
93 static int pcomp(const void *a1, const void *a2)
95 const t_param *p1, *p2;
98 p1 = static_cast<const t_param *>(a1);
99 p2 = static_cast<const t_param *>(a2);
100 if ((pc = (p1->ai()-p2->ai())) != 0)
106 return (p1->aj()-p2->aj());
110 static int dcomp(const void *d1, const void *d2)
112 const t_param *p1, *p2;
115 p1 = static_cast<const t_param *>(d1);
116 p2 = static_cast<const t_param *>(d2);
117 /* First sort by J & K (the two central) atoms */
118 if ((dc = (p1->aj()-p2->aj())) != 0)
122 else if ((dc = (p1->ak()-p2->ak())) != 0)
126 /* Then make sure to put rtp dihedrals before generated ones */
127 else if (was_dihedral_set_in_rtp(p1) &&
128 !was_dihedral_set_in_rtp(p2))
132 else if (!was_dihedral_set_in_rtp(p1) &&
133 was_dihedral_set_in_rtp(p2))
137 /* Then sort by I and J (two outer) atoms */
138 else if ((dc = (p1->ai()-p2->ai())) != 0)
142 else if ((dc = (p1->al()-p2->al())) != 0)
148 // AMBER force fields with type 9 dihedrals can reach here, where we sort on
149 // the contents of the string that names the macro for the parameters.
150 return strcmp(p1->s, p2->s);
155 static bool is_dihedral_on_same_bond(t_param *p1, t_param *p2)
157 return ((p1->aj() == p2->aj()) && (p1->ak() == p2->ak())) ||
158 ((p1->aj() == p2->ak()) && (p1->ak() == p2->aj()));
162 static bool preq(t_param *p1, t_param *p2)
164 return (p1->ai() == p2->ai()) && (p1->aj() == p2->aj());
167 static void rm2par(t_param p[], int *np, peq eq)
180 for (i = 1; (i < (*np)); i++)
182 if (!eq(&p[i], &p[i-1]))
187 /* Index now holds pointers to all the non-equal params,
188 * this only works when p is sorted of course
190 for (i = 0; (i < nind); i++)
192 for (j = 0; (j < MAXATOMLIST); j++)
194 p[i].a[j] = p[index[i]].a[j];
196 for (j = 0; (j < MAXFORCEPARAM); j++)
198 p[i].c[j] = p[index[i]].c[j];
200 if (p[index[i]].a[0] == p[index[i]].a[1])
204 else if (index[i] > i)
206 /* Copy the string only if it comes from somewhere else
207 * otherwise we will end up copying a random (newly freed) pointer.
208 * Since the index is sorted we only have to test for index[i] > i.
210 strcpy(p[i].s, p[index[i]].s);
218 static void cppar(t_param p[], int np, t_params plist[], int ftype)
220 int i, j, nral, nrfp;
229 for (i = 0; (i < np); i++)
231 for (j = 0; (j < nral); j++)
233 ps->param[ps->nr].a[j] = p[i].a[j];
235 for (j = 0; (j < nrfp); j++)
237 ps->param[ps->nr].c[j] = p[i].c[j];
239 for (j = 0; (j < MAXSLEN); j++)
241 ps->param[ps->nr].s[j] = p[i].s[j];
247 static void cpparam(t_param *dest, t_param *src)
251 for (j = 0; (j < MAXATOMLIST); j++)
253 dest->a[j] = src->a[j];
255 for (j = 0; (j < MAXFORCEPARAM); j++)
257 dest->c[j] = src->c[j];
259 for (j = 0; (j < MAXSLEN); j++)
261 dest->s[j] = src->s[j];
265 static void set_p(t_param *p, const int ai[4], const real *c, char *s)
269 for (j = 0; (j < 4); j++)
273 for (j = 0; (j < MAXFORCEPARAM); j++)
288 static int idcomp(const void *a, const void *b)
290 const t_param *pa, *pb;
293 pa = static_cast<const t_param *>(a);
294 pb = static_cast<const t_param *>(b);
295 if ((d = (pa->a[0]-pb->a[0])) != 0)
299 else if ((d = (pa->a[3]-pb->a[3])) != 0)
303 else if ((d = (pa->a[1]-pb->a[1])) != 0)
309 return (pa->a[2]-pb->a[2]);
313 static void sort_id(int nr, t_param ps[])
317 /* First swap order of atoms around if necessary */
318 for (i = 0; (i < nr); i++)
320 if (ps[i].a[3] < ps[i].a[0])
322 tmp = ps[i].a[3]; ps[i].a[3] = ps[i].a[0]; ps[i].a[0] = tmp;
323 tmp = ps[i].a[2]; ps[i].a[2] = ps[i].a[1]; ps[i].a[1] = tmp;
329 qsort(ps, nr, static_cast<size_t>(sizeof(ps[0])), idcomp);
333 static int n_hydro(const int a[], char ***atomname)
338 for (i = 0; (i < 4); i += 3)
340 aname = *atomname[a[i]];
341 c0 = toupper(aname[0]);
346 else if ((static_cast<int>(strlen(aname)) > 1) && (c0 >= '0') && (c0 <= '9'))
348 c1 = toupper(aname[1]);
358 /* Clean up the dihedrals (both generated and read from the .rtp
360 static void clean_dih(t_param *dih, int *ndih, t_param improper[], int nimproper,
361 t_atoms *atoms, bool bKeepAllGeneratedDihedrals,
362 bool bRemoveDihedralIfWithImproper)
367 /* Construct the list of the indices of the dihedrals
368 * (i.e. generated or read) that might be kept. */
369 snew(index, *ndih+1);
370 if (bKeepAllGeneratedDihedrals)
372 fprintf(stderr, "Keeping all generated dihedrals\n");
374 for (i = 0; i < nind; i++)
383 /* Check if generated dihedral i should be removed. The
384 * dihedrals have been sorted by dcomp() above, so all those
385 * on the same two central atoms are together, with those from
386 * the .rtp file preceding those that were automatically
387 * generated. We remove the latter if the former exist. */
388 for (i = 0; i < *ndih; i++)
390 /* Keep the dihedrals that were defined in the .rtp file,
391 * and the dihedrals that were generated and different
392 * from the last one (whether it was generated or not). */
393 if (was_dihedral_set_in_rtp(&dih[i]) ||
395 !is_dihedral_on_same_bond(&dih[i], &dih[i-1]))
404 for (i = 0; i < nind; i++)
406 bool bWasSetInRTP = was_dihedral_set_in_rtp(&dih[index[i]]);
408 if (!bWasSetInRTP && bRemoveDihedralIfWithImproper)
410 /* Remove the dihedral if there is an improper on the same
412 for (j = 0; j < nimproper && bKeep; j++)
414 bKeep = !is_dihedral_on_same_bond(&dih[index[i]], &improper[j]);
420 /* If we don't want all dihedrals, we want to select the
421 * ones with the fewest hydrogens. Note that any generated
422 * dihedrals on the same bond as an .rtp dihedral may have
423 * been already pruned above in the construction of
424 * index[]. However, their parameters are still present,
425 * and l is looping over this dihedral and all of its
426 * pruned siblings. */
427 int bestl = index[i];
428 if (!bKeepAllGeneratedDihedrals && !bWasSetInRTP)
430 /* Minimum number of hydrogens for i and l atoms */
434 is_dihedral_on_same_bond(&dih[index[i]], &dih[l]));
437 int nh = n_hydro(dih[l].a, atoms->atomname);
451 cpparam(&dih[k], &dih[bestl]);
457 for (i = k; i < *ndih; i++)
459 strcpy(dih[i].s, "");
466 static int get_impropers(t_atoms *atoms, t_hackblock hb[], t_param **improper,
469 t_rbondeds *impropers;
470 int nimproper, i, j, k, start, ninc, nalloc;
476 snew(*improper, nalloc);
478 /* Add all the impropers from the residue database to the list. */
483 for (i = 0; (i < atoms->nres); i++)
485 impropers = &hb[i].rb[ebtsIDIHS];
486 for (j = 0; (j < impropers->nb); j++)
489 for (k = 0; (k < 4) && !bStop; k++)
491 ai[k] = search_atom(impropers->b[j].a[k], start,
493 "improper", bAllowMissing);
501 if (nimproper == nalloc)
504 srenew(*improper, nalloc);
507 set_p(&((*improper)[nimproper]), ai, nullptr, impropers->b[j].s);
511 while ((start < atoms->nr) && (atoms->atom[start].resind == i))
521 static int nb_dist(t_nextnb *nnb, int ai, int aj)
533 nrexcl = nnb->nrexcl[ai];
534 for (nre = 1; (nre < nnb->nrex); nre++)
537 for (nrx = 0; (nrx < nrexcl[nre]); nrx++)
539 if ((aj == a[nrx]) && (NRE == -1))
548 static bool is_hydro(t_atoms *atoms, int ai)
550 return ((*(atoms->atomname[ai]))[0] == 'H');
553 static void get_atomnames_min(int n, char **anm,
554 int resind, t_atoms *atoms, const int *a)
558 /* Assume ascending residue numbering */
559 for (m = 0; m < n; m++)
561 if (atoms->atom[a[m]].resind < resind)
565 else if (atoms->atom[a[m]].resind > resind)
573 strcat(anm[m], *(atoms->atomname[a[m]]));
577 static void gen_excls(t_atoms *atoms, t_excls *excls, t_hackblock hb[],
581 int a, astart, i1, i2, itmp;
587 for (a = 0; a < atoms->nr; a++)
589 r = atoms->atom[a].resind;
590 if (a == atoms->nr-1 || atoms->atom[a+1].resind != r)
592 hbexcl = &hb[r].rb[ebtsEXCLS];
594 for (e = 0; e < hbexcl->nb; e++)
596 anm = hbexcl->b[e].a[0];
597 i1 = search_atom(anm, astart, atoms,
598 "exclusion", bAllowMissing);
599 anm = hbexcl->b[e].a[1];
600 i2 = search_atom(anm, astart, atoms,
601 "exclusion", bAllowMissing);
602 if (i1 != -1 && i2 != -1)
610 srenew(excls[i1].e, excls[i1].nr+1);
611 excls[i1].e[excls[i1].nr] = i2;
620 for (a = 0; a < atoms->nr; a++)
624 std::sort(excls[a].e, excls[a].e+excls[a].nr);
629 static void remove_excl(t_excls *excls, int remove)
633 for (i = remove+1; i < excls->nr; i++)
635 excls->e[i-1] = excls->e[i];
641 void clean_excls(t_nextnb *nnb, int nrexcl, t_excls excls[])
643 int i, j, j1, k, k1, l, l1, e;
648 /* extract all i-j-k-l neighbours from nnb struct */
649 for (i = 0; (i < nnb->nr); i++)
651 /* For all particles */
654 for (j = 0; (j < nnb->nrexcl[i][1]); j++)
656 /* For all first neighbours */
657 j1 = nnb->a[i][1][j];
659 for (e = 0; e < excl->nr; e++)
661 if (excl->e[e] == j1)
663 remove_excl(excl, e);
669 for (k = 0; (k < nnb->nrexcl[j1][1]); k++)
671 /* For all first neighbours of j1 */
672 k1 = nnb->a[j1][1][k];
674 for (e = 0; e < excl->nr; e++)
676 if (excl->e[e] == k1)
678 remove_excl(excl, e);
684 for (l = 0; (l < nnb->nrexcl[k1][1]); l++)
686 /* For all first neighbours of k1 */
687 l1 = nnb->a[k1][1][l];
689 for (e = 0; e < excl->nr; e++)
691 if (excl->e[e] == l1)
693 remove_excl(excl, e);
705 void generate_excls(t_nextnb *nnb, int nrexcl, t_excls excls[])
710 for (N = 1; (N < std::min(nrexcl, nnb->nrex)); N++)
712 /* extract all i-j-k-l neighbours from nnb struct */
713 for (i = 0; (i < nnb->nr); i++)
715 /* For all particles */
718 excl->nr += nnb->nrexcl[i][N];
719 srenew(excl->e, excl->nr);
720 for (j = 0; (j < nnb->nrexcl[i][N]); j++)
722 /* For all first neighbours */
723 if (nnb->a[i][N][j] != i)
725 excl->e[n++] = nnb->a[i][N][j];
732 /* Generate pairs, angles and dihedrals from .rtp settings */
733 void gen_pad(t_nextnb *nnb, t_atoms *atoms, t_restp rtp[],
734 t_params plist[], t_excls excls[], t_hackblock hb[],
737 t_param *ang, *dih, *pai, *improper;
738 t_rbondeds *hbang, *hbdih;
741 int res, minres, maxres;
742 int i, j, j1, k, k1, l, l1, m, n, i1, i2;
743 int ninc, maxang, maxdih, maxpai;
744 int nang, ndih, npai, nimproper, nbd;
748 /* These are the angles, dihedrals and pairs that we generate
749 * from the bonds. The ones that are already there from the rtp file
756 maxang = maxdih = maxpai = ninc;
762 for (i = 0; i < 4; i++)
769 gen_excls(atoms, excls, hb, bAllowMissing);
770 /* mark all entries as not matched yet */
771 for (i = 0; i < atoms->nres; i++)
773 for (j = 0; j < ebtsNR; j++)
775 for (k = 0; k < hb[i].rb[j].nb; k++)
777 hb[i].rb[j].b[k].match = FALSE;
783 /* Extract all i-j-k-l neighbours from nnb struct to generate all
784 * angles and dihedrals. */
785 for (i = 0; (i < nnb->nr); i++)
787 /* For all particles */
788 for (j = 0; (j < nnb->nrexcl[i][1]); j++)
790 /* For all first neighbours */
791 j1 = nnb->a[i][1][j];
792 for (k = 0; (k < nnb->nrexcl[j1][1]); k++)
794 /* For all first neighbours of j1 */
795 k1 = nnb->a[j1][1][k];
798 /* Generate every angle only once */
809 ang[nang].c0() = NOTSET;
810 ang[nang].c1() = NOTSET;
811 set_p_string(&(ang[nang]), "");
814 minres = atoms->atom[ang[nang].a[0]].resind;
816 for (m = 1; m < 3; m++)
818 minres = std::min(minres, atoms->atom[ang[nang].a[m]].resind);
819 maxres = std::max(maxres, atoms->atom[ang[nang].a[m]].resind);
821 res = 2*minres-maxres;
824 res += maxres-minres;
825 get_atomnames_min(3, anm, res, atoms, ang[nang].a);
826 hbang = &hb[res].rb[ebtsANGLES];
827 for (l = 0; (l < hbang->nb); l++)
829 if (strcmp(anm[1], hbang->b[l].aj()) == 0)
832 for (m = 0; m < 3; m += 2)
835 ((strcmp(anm[m], hbang->b[l].ai()) == 0) &&
836 (strcmp(anm[2-m], hbang->b[l].ak()) == 0)));
840 set_p_string(&(ang[nang]), hbang->b[l].s);
841 /* Mark that we found a match for this entry */
842 hbang->b[l].match = TRUE;
847 while (res < maxres);
851 /* Generate every dihedral, 1-4 exclusion and 1-4 interaction
855 for (l = 0; (l < nnb->nrexcl[k1][1]); l++)
857 /* For all first neighbours of k1 */
858 l1 = nnb->a[k1][1][l];
859 if ((l1 != i) && (l1 != j1))
870 for (m = 0; m < MAXFORCEPARAM; m++)
872 dih[ndih].c[m] = NOTSET;
874 set_p_string(&(dih[ndih]), "");
878 minres = atoms->atom[dih[ndih].a[0]].resind;
880 for (m = 1; m < 4; m++)
882 minres = std::min(minres, atoms->atom[dih[ndih].a[m]].resind);
883 maxres = std::max(maxres, atoms->atom[dih[ndih].a[m]].resind);
885 res = 2*minres-maxres;
888 res += maxres-minres;
889 get_atomnames_min(4, anm, res, atoms, dih[ndih].a);
890 hbdih = &hb[res].rb[ebtsPDIHS];
891 for (n = 0; (n < hbdih->nb); n++)
894 for (m = 0; m < 2; m++)
897 ((strcmp(anm[3*m], hbdih->b[n].ai()) == 0) &&
898 (strcmp(anm[1+m], hbdih->b[n].aj()) == 0) &&
899 (strcmp(anm[2-m], hbdih->b[n].ak()) == 0) &&
900 (strcmp(anm[3-3*m], hbdih->b[n].al()) == 0)));
904 set_p_string(&dih[ndih], hbdih->b[n].s);
905 /* Mark that we found a match for this entry */
906 hbdih->b[n].match = TRUE;
908 /* Set the last parameter to be able to see
909 if the dihedral was in the rtp list.
911 dih[ndih].c[MAXFORCEPARAM-1] = DIHEDRAL_WAS_SET_IN_RTP;
914 /* Set the next direct in case the rtp contains
915 multiple entries for this dihedral.
926 for (m = 0; m < MAXFORCEPARAM; m++)
928 dih[ndih].c[m] = NOTSET;
933 while (res < maxres);
946 for (m = 0; m < MAXFORCEPARAM; m++)
948 dih[ndih].c[m] = NOTSET;
950 set_p_string(&(dih[ndih]), "");
954 nbd = nb_dist(nnb, i, l1);
957 i1 = std::min(i, l1);
958 i2 = std::max(i, l1);
960 for (m = 0; m < excls[i1].nr; m++)
962 bExcl = bExcl || excls[i1].e[m] == i2;
966 if (rtp[0].bGenerateHH14Interactions ||
967 !(is_hydro(atoms, i1) && is_hydro(atoms, i2)))
976 pai[npai].c0() = NOTSET;
977 pai[npai].c1() = NOTSET;
978 set_p_string(&(pai[npai]), "");
993 /* The above approach is great in that we double-check that e.g. an angle
994 * really corresponds to three atoms connected by bonds, but this is not
995 * generally true. Go through the angle and dihedral hackblocks to add
996 * entries that we have not yet marked as matched when going through bonds.
998 for (i = 0; i < atoms->nres; i++)
1000 /* Add remaining angles from hackblock */
1001 hbang = &hb[i].rb[ebtsANGLES];
1002 for (j = 0; j < hbang->nb; j++)
1004 if (hbang->b[j].match)
1006 /* We already used this entry, continue to the next */
1009 /* Hm - entry not used, let's see if we can find all atoms */
1013 srenew(ang, maxang);
1016 for (k = 0; k < 3 && bFound; k++)
1018 p = hbang->b[j].a[k];
1025 else if (p[0] == '+')
1030 ang[nang].a[k] = search_res_atom(p, res, atoms, "angle", TRUE);
1031 bFound = (ang[nang].a[k] != -1);
1033 ang[nang].c0() = NOTSET;
1034 ang[nang].c1() = NOTSET;
1038 set_p_string(&(ang[nang]), hbang->b[j].s);
1039 hbang->b[j].match = TRUE;
1040 /* Incrementing nang means we save this angle */
1045 /* Add remaining dihedrals from hackblock */
1046 hbdih = &hb[i].rb[ebtsPDIHS];
1047 for (j = 0; j < hbdih->nb; j++)
1049 if (hbdih->b[j].match)
1051 /* We already used this entry, continue to the next */
1054 /* Hm - entry not used, let's see if we can find all atoms */
1058 srenew(dih, maxdih);
1061 for (k = 0; k < 4 && bFound; k++)
1063 p = hbdih->b[j].a[k];
1070 else if (p[0] == '+')
1075 dih[ndih].a[k] = search_res_atom(p, res, atoms, "dihedral", TRUE);
1076 bFound = (dih[ndih].a[k] != -1);
1078 for (m = 0; m < MAXFORCEPARAM; m++)
1080 dih[ndih].c[m] = NOTSET;
1085 set_p_string(&(dih[ndih]), hbdih->b[j].s);
1086 hbdih->b[j].match = TRUE;
1087 /* Incrementing ndih means we save this dihedral */
1094 /* Sort angles with respect to j-i-k (middle atom first) */
1097 qsort(ang, nang, static_cast<size_t>(sizeof(ang[0])), acomp);
1100 /* Sort dihedrals with respect to j-k-i-l (middle atoms first) */
1103 qsort(dih, ndih, static_cast<size_t>(sizeof(dih[0])), dcomp);
1106 /* Sort the pairs */
1109 qsort(pai, npai, static_cast<size_t>(sizeof(pai[0])), pcomp);
1113 /* Remove doubles, could occur in 6-rings, such as phenyls,
1114 maybe one does not want this when fudgeQQ < 1.
1116 fprintf(stderr, "Before cleaning: %d pairs\n", npai);
1117 rm2par(pai, &npai, preq);
1120 /* Get the impropers from the database */
1121 nimproper = get_impropers(atoms, hb, &improper, bAllowMissing);
1123 /* Sort the impropers */
1124 sort_id(nimproper, improper);
1128 fprintf(stderr, "Before cleaning: %d dihedrals\n", ndih);
1129 clean_dih(dih, &ndih, improper, nimproper, atoms,
1130 rtp[0].bKeepAllGeneratedDihedrals,
1131 rtp[0].bRemoveDihedralIfWithImproper);
1134 /* Now we have unique lists of angles and dihedrals
1135 * Copy them into the destination struct
1137 cppar(ang, nang, plist, F_ANGLES);
1138 cppar(dih, ndih, plist, F_PDIHS);
1139 cppar(improper, nimproper, plist, F_IDIHS);
1140 cppar(pai, npai, plist, F_LJ14);
1142 /* Remove all exclusions which are within nrexcl */
1143 clean_excls(nnb, rtp[0].nrexcl, excls);