void gen_pad(t_nextnb *nnb, t_atoms *atoms, int nrexcl, bool bH14, t_params plist[], t_excls excls[], t_hackblock hb[], bool bAlldih, bool bRemoveDih, bool bMissing) { t_param *ang,*dih,*pai,*idih; t_rbondeds *hbang, *hbdih; char **anm; 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,nidih,nbd; int nFound; 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,bMissing); /* extract all i-j-k-l neighbours from nnb struct */ 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 = min(minres,atoms->atom[ang[nang].a[m]].resind); maxres = 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); } } } } 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 = min(minres,atoms->atom[dih[ndih].a[m]].resind); maxres = 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); /* Set the last parameter to be able to see if the dihedral was in the rtp list. */ dih[ndih].c[MAXFORCEPARAM-1] = 0; 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 = min(i,l1); i2 = max(i,l1); bExcl = FALSE; for(m=0; m<excls[i1].nr; m++) bExcl = bExcl || excls[i1].e[m]==i2; if (!bExcl) { if (bH14 || !(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++; } } } } } } } } } /* 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 */ nidih = get_impropers(atoms,hb,&idih,bMissing); /* Sort the impropers */ sort_id(nidih,idih); if (ndih > 0) { /* Remove dihedrals which are impropers and when bAlldih is not set remove multiple dihedrals over one bond. */ fprintf(stderr,"Before cleaning: %d dihedrals\n",ndih); clean_dih(dih,&ndih,idih,nidih,atoms,bAlldih,bRemoveDih); } /* 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(idih,nidih,plist,F_IDIHS); cppar(pai, npai, plist,F_LJ14); /* Remove all exclusions which are within nrexcl */ clean_excls(nnb,nrexcl,excls); sfree(ang); sfree(dih); sfree(idih); sfree(pai); }
/* 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); }