static void do_ssbonds(t_params *ps,int natoms,t_atom atom[],char **aname[], int nssbonds,t_ssbond *ssbonds,gmx_bool bAllowMissing) { int i,ri,rj; atom_id ai,aj; for(i=0; (i<nssbonds); i++) { ri = ssbonds[i].res1; rj = ssbonds[i].res2; ai = search_res_atom(ssbonds[i].a1,ri,natoms,atom,aname, "special bond",bAllowMissing); aj = search_res_atom(ssbonds[i].a2,rj,natoms,atom,aname, "special bond",bAllowMissing); if ((ai == NO_ATID) || (aj == NO_ATID)) gmx_fatal(FARGS,"Trying to make impossible special bond (%s-%s)!", ssbonds[i].a1,ssbonds[i].a2); add_param(ps,ai,aj,NULL,NULL); } }
/* Generate pairs, angles and dihedrals from .rtp settings */ void gen_pad(t_nextnb *nnb, t_atoms *atoms, t_restp rtp[], t_params plist[], t_excls excls[], t_hackblock hb[], gmx_bool bAllowMissing) { t_param *ang, *dih, *pai, *improper; t_rbondeds *hbang, *hbdih; char **anm; const char *p; int res, minres, maxres; int i, j, j1, k, k1, l, l1, m, n, i1, i2; int ninc, maxang, maxdih, maxpai; int nang, ndih, npai, nimproper, nbd; int nFound; gmx_bool bFound, bExcl; /* These are the angles, dihedrals and pairs that we generate * from the bonds. The ones that are already there from the rtp file * will be retained. */ nang = 0; npai = 0; ndih = 0; ninc = 500; maxang = maxdih = maxpai = ninc; snew(ang, maxang); snew(dih, maxdih); snew(pai, maxpai); snew(anm, 4); for (i = 0; i < 4; i++) { snew(anm[i], 12); } if (hb) { gen_excls(atoms, excls, hb, bAllowMissing); /* mark all entries as not matched yet */ for (i = 0; i < atoms->nres; i++) { for (j = 0; j < ebtsNR; j++) { for (k = 0; k < hb[i].rb[j].nb; k++) { hb[i].rb[j].b[k].match = FALSE; } } } } /* Extract all i-j-k-l neighbours from nnb struct to generate all * angles and dihedrals. */ for (i = 0; (i < nnb->nr); i++) { /* For all particles */ for (j = 0; (j < nnb->nrexcl[i][1]); j++) { /* For all first neighbours */ j1 = nnb->a[i][1][j]; for (k = 0; (k < nnb->nrexcl[j1][1]); k++) { /* For all first neighbours of j1 */ k1 = nnb->a[j1][1][k]; if (k1 != i) { /* Generate every angle only once */ if (i < k1) { if (nang == maxang) { maxang += ninc; srenew(ang, maxang); } ang[nang].ai() = i; ang[nang].aj() = j1; ang[nang].ak() = k1; ang[nang].c0() = NOTSET; ang[nang].c1() = NOTSET; set_p_string(&(ang[nang]), ""); if (hb) { minres = atoms->atom[ang[nang].a[0]].resind; maxres = minres; for (m = 1; m < 3; m++) { minres = std::min(minres, atoms->atom[ang[nang].a[m]].resind); maxres = std::max(maxres, atoms->atom[ang[nang].a[m]].resind); } res = 2*minres-maxres; do { res += maxres-minres; get_atomnames_min(3, anm, res, atoms, ang[nang].a); hbang = &hb[res].rb[ebtsANGLES]; for (l = 0; (l < hbang->nb); l++) { if (strcmp(anm[1], hbang->b[l].aj()) == 0) { bFound = FALSE; for (m = 0; m < 3; m += 2) { bFound = (bFound || ((strcmp(anm[m], hbang->b[l].ai()) == 0) && (strcmp(anm[2-m], hbang->b[l].ak()) == 0))); } if (bFound) { set_p_string(&(ang[nang]), hbang->b[l].s); /* Mark that we found a match for this entry */ hbang->b[l].match = TRUE; } } } } while (res < maxres); } nang++; } /* Generate every dihedral, 1-4 exclusion and 1-4 interaction only once */ if (j1 < k1) { for (l = 0; (l < nnb->nrexcl[k1][1]); l++) { /* For all first neighbours of k1 */ l1 = nnb->a[k1][1][l]; if ((l1 != i) && (l1 != j1)) { if (ndih == maxdih) { maxdih += ninc; srenew(dih, maxdih); } dih[ndih].ai() = i; dih[ndih].aj() = j1; dih[ndih].ak() = k1; dih[ndih].al() = l1; for (m = 0; m < MAXFORCEPARAM; m++) { dih[ndih].c[m] = NOTSET; } set_p_string(&(dih[ndih]), ""); nFound = 0; if (hb) { minres = atoms->atom[dih[ndih].a[0]].resind; maxres = minres; for (m = 1; m < 4; m++) { minres = std::min(minres, atoms->atom[dih[ndih].a[m]].resind); maxres = std::max(maxres, atoms->atom[dih[ndih].a[m]].resind); } res = 2*minres-maxres; do { res += maxres-minres; get_atomnames_min(4, anm, res, atoms, dih[ndih].a); hbdih = &hb[res].rb[ebtsPDIHS]; for (n = 0; (n < hbdih->nb); n++) { bFound = FALSE; for (m = 0; m < 2; m++) { bFound = (bFound || ((strcmp(anm[3*m], hbdih->b[n].ai()) == 0) && (strcmp(anm[1+m], hbdih->b[n].aj()) == 0) && (strcmp(anm[2-m], hbdih->b[n].ak()) == 0) && (strcmp(anm[3-3*m], hbdih->b[n].al()) == 0))); } if (bFound) { set_p_string(&dih[ndih], hbdih->b[n].s); /* Mark that we found a match for this entry */ hbdih->b[n].match = TRUE; /* Set the last parameter to be able to see if the dihedral was in the rtp list. */ dih[ndih].c[MAXFORCEPARAM-1] = DIHEDRAL_WAS_SET_IN_RTP; nFound++; ndih++; /* Set the next direct in case the rtp contains multiple entries for this dihedral. */ if (ndih == maxdih) { maxdih += ninc; srenew(dih, maxdih); } dih[ndih].ai() = i; dih[ndih].aj() = j1; dih[ndih].ak() = k1; dih[ndih].al() = l1; for (m = 0; m < MAXFORCEPARAM; m++) { dih[ndih].c[m] = NOTSET; } } } } while (res < maxres); } if (nFound == 0) { if (ndih == maxdih) { maxdih += ninc; srenew(dih, maxdih); } dih[ndih].ai() = i; dih[ndih].aj() = j1; dih[ndih].ak() = k1; dih[ndih].al() = l1; for (m = 0; m < MAXFORCEPARAM; m++) { dih[ndih].c[m] = NOTSET; } set_p_string(&(dih[ndih]), ""); ndih++; } nbd = nb_dist(nnb, i, l1); if (debug) { fprintf(debug, "Distance (%d-%d) = %d\n", i+1, l1+1, nbd); } if (nbd == 3) { i1 = std::min(i, l1); i2 = std::max(i, l1); bExcl = FALSE; for (m = 0; m < excls[i1].nr; m++) { bExcl = bExcl || excls[i1].e[m] == i2; } if (!bExcl) { if (rtp[0].bGenerateHH14Interactions || !(is_hydro(atoms, i1) && is_hydro(atoms, i2))) { if (npai == maxpai) { maxpai += ninc; srenew(pai, maxpai); } pai[npai].ai() = i1; pai[npai].aj() = i2; pai[npai].c0() = NOTSET; pai[npai].c1() = NOTSET; set_p_string(&(pai[npai]), ""); npai++; } } } } } } } } } } if (hb) { /* The above approach is great in that we double-check that e.g. an angle * really corresponds to three atoms connected by bonds, but this is not * generally true. Go through the angle and dihedral hackblocks to add * entries that we have not yet marked as matched when going through bonds. */ for (i = 0; i < atoms->nres; i++) { /* Add remaining angles from hackblock */ hbang = &hb[i].rb[ebtsANGLES]; for (j = 0; j < hbang->nb; j++) { if (hbang->b[j].match == TRUE) { /* We already used this entry, continue to the next */ continue; } /* Hm - entry not used, let's see if we can find all atoms */ if (nang == maxang) { maxang += ninc; srenew(ang, maxang); } bFound = TRUE; for (k = 0; k < 3 && bFound; k++) { p = hbang->b[j].a[k]; res = i; if (p[0] == '-') { p++; res--; } else if (p[0] == '+') { p++; res++; } ang[nang].a[k] = search_res_atom(p, res, atoms, "angle", TRUE); bFound = (ang[nang].a[k] != NO_ATID); } ang[nang].c0() = NOTSET; ang[nang].c1() = NOTSET; if (bFound) { set_p_string(&(ang[nang]), hbang->b[j].s); hbang->b[j].match = TRUE; /* Incrementing nang means we save this angle */ nang++; } } /* Add remaining dihedrals from hackblock */ hbdih = &hb[i].rb[ebtsPDIHS]; for (j = 0; j < hbdih->nb; j++) { if (hbdih->b[j].match == TRUE) { /* We already used this entry, continue to the next */ continue; } /* Hm - entry not used, let's see if we can find all atoms */ if (ndih == maxdih) { maxdih += ninc; srenew(dih, maxdih); } bFound = TRUE; for (k = 0; k < 4 && bFound; k++) { p = hbdih->b[j].a[k]; res = i; if (p[0] == '-') { p++; res--; } else if (p[0] == '+') { p++; res++; } dih[ndih].a[k] = search_res_atom(p, res, atoms, "dihedral", TRUE); bFound = (dih[ndih].a[k] != NO_ATID); } for (m = 0; m < MAXFORCEPARAM; m++) { dih[ndih].c[m] = NOTSET; } if (bFound) { set_p_string(&(dih[ndih]), hbdih->b[j].s); hbdih->b[j].match = TRUE; /* Incrementing ndih means we save this dihedral */ ndih++; } } } } /* Sort angles with respect to j-i-k (middle atom first) */ if (nang > 1) { qsort(ang, nang, (size_t)sizeof(ang[0]), acomp); } /* Sort dihedrals with respect to j-k-i-l (middle atoms first) */ if (ndih > 1) { qsort(dih, ndih, (size_t)sizeof(dih[0]), dcomp); } /* Sort the pairs */ if (npai > 1) { qsort(pai, npai, (size_t)sizeof(pai[0]), pcomp); } if (npai > 0) { /* Remove doubles, could occur in 6-rings, such as phenyls, maybe one does not want this when fudgeQQ < 1. */ fprintf(stderr, "Before cleaning: %d pairs\n", npai); rm2par(pai, &npai, preq); } /* Get the impropers from the database */ nimproper = get_impropers(atoms, hb, &improper, bAllowMissing); /* Sort the impropers */ sort_id(nimproper, improper); if (ndih > 0) { fprintf(stderr, "Before cleaning: %d dihedrals\n", ndih); clean_dih(dih, &ndih, improper, nimproper, atoms, rtp[0].bKeepAllGeneratedDihedrals, rtp[0].bRemoveDihedralIfWithImproper); } /* Now we have unique lists of angles and dihedrals * Copy them into the destination struct */ cppar(ang, nang, plist, F_ANGLES); cppar(dih, ndih, plist, F_PDIHS); cppar(improper, nimproper, plist, F_IDIHS); cppar(pai, npai, plist, F_LJ14); /* Remove all exclusions which are within nrexcl */ clean_excls(nnb, rtp[0].nrexcl, excls); sfree(ang); sfree(dih); sfree(improper); sfree(pai); }