Merge branch 'release-4-6'
[alexxy/gromacs.git] / src / gromacs / gmxpreprocess / gen_ad.c
1 /*
2  * 
3  *                This source code is part of
4  * 
5  *                 G   R   O   M   A   C   S
6  * 
7  *          GROningen MAchine for Chemical Simulations
8  * 
9  *                        VERSION 3.2.0
10  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12  * Copyright (c) 2001-2004, The GROMACS development team,
13  * check out http://www.gromacs.org for more information.
14
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  * 
20  * If you want to redistribute modifications, please consider that
21  * scientific software is very special. Version control is crucial -
22  * bugs must be traceable. We will be happy to consider code for
23  * inclusion in the official distribution, but derived work must not
24  * be called official GROMACS. Details are found in the README & COPYING
25  * files - if they are missing, get the official version at www.gromacs.org.
26  * 
27  * To help us fund GROMACS development, we humbly ask that you cite
28  * the papers on the package - you can find them in the top README file.
29  * 
30  * For more info, check our website at http://www.gromacs.org
31  * 
32  * And Hey:
33  * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
34  */
35 /* This file is completely threadsafe - keep it that way! */
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <math.h>
41 #include <ctype.h>
42 #include "sysstuff.h"
43 #include "macros.h"
44 #include "smalloc.h"
45 #include "string2.h"
46 #include "confio.h"
47 #include "vec.h"
48 #include "pbc.h"
49 #include "toputil.h"
50 #include "topio.h"
51 #include "gpp_nextnb.h"
52 #include "symtab.h"
53 #include "macros.h"
54 #include "gmx_fatal.h"
55 #include "pgutil.h"
56 #include "resall.h"
57 #include "gen_ad.h"
58
59 typedef gmx_bool (*peq)(t_param *p1, t_param *p2);
60
61 static int acomp(const void *a1, const void *a2)
62 {
63   t_param *p1,*p2;
64   int     ac;
65   
66   p1=(t_param *)a1;
67   p2=(t_param *)a2;
68   if ((ac=(p1->AJ-p2->AJ))!=0)
69     return ac;
70   else if ((ac=(p1->AI-p2->AI))!=0)
71     return ac;
72   else 
73     return (p1->AK-p2->AK);
74 }
75
76 static int pcomp(const void *a1, const void *a2)
77 {
78   t_param *p1,*p2;
79   int     pc;
80   
81   p1=(t_param *)a1;
82   p2=(t_param *)a2;
83   if ((pc=(p1->AI-p2->AI))!=0)
84     return pc;
85   else 
86     return (p1->AJ-p2->AJ);
87 }
88
89 static int dcomp(const void *d1, const void *d2)
90 {
91   t_param *p1,*p2;
92   int     dc;
93   
94   p1=(t_param *)d1;
95   p2=(t_param *)d2;
96   /* First sort by J & K (the two central) atoms */
97   if ((dc=(p1->AJ-p2->AJ))!=0)
98     return dc;
99   else if ((dc=(p1->AK-p2->AK))!=0)
100     return dc;
101   /* Then make sure to put rtp dihedrals before generated ones */
102   else if (p1->c[MAXFORCEPARAM-1]==0 && p2->c[MAXFORCEPARAM-1]==NOTSET)
103     return -1;
104   else if (p1->c[MAXFORCEPARAM-1]==NOTSET && p2->c[MAXFORCEPARAM-1]==0)
105     return 1;
106   /* Finally, sort by I and J (two outer) atoms */
107   else if ((dc=(p1->AI-p2->AI))!=0)
108     return dc;
109   else
110     return (p1->AL-p2->AL);
111 }
112
113 static gmx_bool deq(t_param *p1, t_param *p2)
114 {
115   if (((p1->AJ==p2->AJ) && (p1->AK==p2->AK)) ||
116       ((p1->AJ==p2->AK) && (p1->AK==p2->AJ)))
117     return TRUE;
118   else
119     return FALSE;
120 }
121
122
123 static gmx_bool remove_dih(t_param *p, int i, int np)
124      /* check if dihedral p[i] should be removed */
125 {
126   gmx_bool bRem;
127   int j;
128
129   if (p[i].c[MAXFORCEPARAM-1]==NOTSET) {
130     if (i>0)
131       bRem = deq(&p[i],&p[i-1]);
132     else
133       bRem = FALSE;
134     /* also remove p[i] if there is a dihedral on the same bond
135        which has parameters set */
136     j=i+1;
137     while (!bRem && (j<np) && deq(&p[i],&p[j])) {
138       bRem = (p[j].c[MAXFORCEPARAM-1] != NOTSET);
139       j++;
140     }
141   } else
142     bRem = FALSE;
143
144   return bRem;
145 }
146
147 static gmx_bool preq(t_param *p1, t_param *p2)
148 {
149   if ((p1->AI==p2->AI) && (p1->AJ==p2->AJ))
150     return TRUE;
151   else 
152     return FALSE;
153 }
154
155 static void rm2par(t_param p[], int *np, peq eq)
156 {
157   int *index,nind;
158   int i,j;
159
160   if ((*np)==0)
161     return;
162
163   snew(index,*np);
164   nind=0;
165     index[nind++]=0;
166   for(i=1; (i<(*np)); i++) 
167     if (!eq(&p[i],&p[i-1]))
168       index[nind++]=i;
169   /* Index now holds pointers to all the non-equal params,
170    * this only works when p is sorted of course
171    */
172   for(i=0; (i<nind); i++) {
173     for(j=0; (j<MAXATOMLIST); j++)
174       p[i].a[j]=p[index[i]].a[j];
175     for(j=0; (j<MAXFORCEPARAM); j++)
176       p[i].c[j]=p[index[i]].c[j];
177     if (p[index[i]].a[0] == p[index[i]].a[1]) {
178       if (debug)  
179         fprintf(debug,
180                 "Something VERY strange is going on in rm2par (gen_ad.c)\n"
181                 "a[0] %u a[1] %u a[2] %u a[3] %u\n",
182                 p[i].a[0],p[i].a[1],p[i].a[2],p[i].a[3]);
183       strcpy(p[i].s,"");
184     } else if (index[i] > i) {
185       /* Copy the string only if it comes from somewhere else 
186        * otherwise we will end up copying a random (newly freed) pointer.
187        * Since the index is sorted we only have to test for index[i] > i.
188        */ 
189       strcpy(p[i].s,p[index[i]].s);
190     }
191   }
192   (*np)=nind;
193
194   sfree(index);
195 }
196
197 static void cppar(t_param p[], int np, t_params plist[], int ftype)
198 {
199   int      i,j,nral,nrfp;
200   t_params *ps;
201
202   ps   = &plist[ftype];
203   nral = NRAL(ftype);
204   nrfp = NRFP(ftype);
205   
206   /* Keep old stuff */
207   pr_alloc(np,ps);
208   for(i=0; (i<np); i++) {
209     for(j=0; (j<nral); j++)
210       ps->param[ps->nr].a[j] = p[i].a[j];
211     for(j=0; (j<nrfp); j++)
212       ps->param[ps->nr].c[j] = p[i].c[j];
213     for(j=0; (j<MAXSLEN); j++)
214       ps->param[ps->nr].s[j] = p[i].s[j];
215     ps->nr++;
216   }
217 }
218
219 static void cpparam(t_param *dest, t_param *src)
220 {
221   int j;
222
223   for(j=0; (j<MAXATOMLIST); j++)
224     dest->a[j] = src->a[j];
225   for(j=0; (j<MAXFORCEPARAM); j++)
226     dest->c[j] = src->c[j];
227   for(j=0; (j<MAXSLEN); j++)
228     dest->s[j] = src->s[j];
229 }
230
231 static void set_p(t_param *p, atom_id ai[4], real *c, char *s)
232 {
233   int j;
234
235   for(j=0; (j<4); j++)
236     p->a[j]=ai[j];
237   for(j=0; (j<MAXFORCEPARAM); j++)
238     if (c)
239       p->c[j]=c[j];
240     else
241       p->c[j]=NOTSET;
242
243   set_p_string(p,s);
244 }
245
246 static int int_comp(const void *a,const void *b)
247 {
248   return (*(int *)a) - (*(int *)b);
249 }
250
251 static int atom_id_comp(const void *a,const void *b)
252 {
253   return (*(atom_id *)a) - (*(atom_id *)b);
254 }
255
256 static int eq_imp(atom_id a1[],atom_id a2[])
257 {
258   int b1[4],b2[4];
259   int j;
260
261   for(j=0; (j<4); j++) {
262     b1[j]=a1[j];
263     b2[j]=a2[j];
264   }
265   qsort(b1,4,(size_t)sizeof(b1[0]),int_comp);
266   qsort(b2,4,(size_t)sizeof(b2[0]),int_comp);
267
268   for(j=0; (j<4); j++)
269     if (b1[j] != b2[j])
270       return FALSE;
271
272   return TRUE;
273 }
274
275 static int idcomp(const void *a,const void *b)
276 {
277   t_param *pa,*pb;
278   int     d;
279   
280   pa=(t_param *)a;
281   pb=(t_param *)b;
282   if ((d=(pa->a[0]-pb->a[0])) != 0)
283     return d;
284   else if ((d=(pa->a[3]-pb->a[3])) != 0)
285     return d;
286   else if ((d=(pa->a[1]-pb->a[1])) != 0)
287     return d;
288   else
289     return (int) (pa->a[2]-pb->a[2]);
290 }
291
292 static void sort_id(int nr,t_param ps[])
293 {
294   int i,tmp;
295   
296   /* First swap order of atoms around if necessary */
297   for(i=0; (i<nr); i++) {
298     if (ps[i].a[3] < ps[i].a[0]) {
299       tmp = ps[i].a[3]; ps[i].a[3] = ps[i].a[0]; ps[i].a[0] = tmp;
300       tmp = ps[i].a[2]; ps[i].a[2] = ps[i].a[1]; ps[i].a[1] = tmp;
301     }
302   }
303   /* Now sort it */
304   if (nr > 1)
305     qsort(ps,nr,(size_t)sizeof(ps[0]),idcomp);
306 }
307
308 static int n_hydro(atom_id a[],char ***atomname)
309 {
310   int i,nh=0;
311   char c0,c1,*aname;
312
313   for(i=0; (i<4); i+=3) {
314     aname=*atomname[a[i]];
315     c0=toupper(aname[0]);
316     if (c0 == 'H')
317       nh++;
318     else if (((int)strlen(aname) > 1) && (c0 >= '0') && (c0 <= '9')) {
319       c1=toupper(aname[1]);
320       if (c1 == 'H')
321         nh++;
322     }
323   }
324   return nh;
325 }
326
327 static void clean_dih(t_param *dih, int *ndih,t_param idih[],int nidih,
328                       t_atoms *atoms,gmx_bool bAlldih, gmx_bool bRemoveDih)
329 {
330   int  i,j,k,l;
331   int  *index,nind;
332   gmx_bool bIsSet,bKeep;
333   int  bestl,nh,minh;
334   
335   snew(index,*ndih+1);
336   if (bAlldih) {
337     fprintf(stderr,"Keeping all generated dihedrals\n");
338     nind = *ndih;
339     for(i=0; i<nind; i++) 
340       index[i] = i;
341     index[nind] = *ndih;
342   } else {
343     /* Make an index of all dihedrals over each bond */
344     nind = 0;
345     for(i=0; i<*ndih; i++) 
346       if (!remove_dih(dih,i,*ndih)) 
347         index[nind++]=i;
348     index[nind] = *ndih;
349   }
350
351   /* if we don't want all dihedrals, we need to select the ones with the 
352    *  fewest hydrogens
353    */
354   
355   k=0;
356   for(i=0; i<nind; i++) {
357     bIsSet = (dih[index[i]].c[MAXFORCEPARAM-1] != NOTSET);
358     bKeep = TRUE;
359     if (!bIsSet && bRemoveDih)
360       /* remove the dihedral if there is an improper on the same bond */
361       for(j=0; (j<nidih) && bKeep; j++)
362         bKeep = !deq(&dih[index[i]],&idih[j]);
363
364     if (bKeep) {
365       /* Now select the "fittest" dihedral:
366        * the one with as few hydrogens as possible 
367        */
368       
369       /* Best choice to get dihedral from */
370       bestl=index[i];
371       if (!bAlldih && !bIsSet) {
372         /* Minimum number of hydrogens for i and l atoms */
373         minh=2;
374         for(l=index[i]; (l<index[i+1]) && deq(&dih[index[i]],&dih[l]); l++) {
375           if ((nh=n_hydro(dih[l].a,atoms->atomname)) < minh) {
376             minh=nh;
377             bestl=l;
378           }
379           if (minh == 0)
380             break;
381         }
382       }
383       if (k != bestl)
384         cpparam(&(dih[k]),&dih[bestl]);
385       k++;
386     }
387   }
388
389   for (i=k; i<*ndih; i++)
390     strcpy(dih[i].s,"");
391   *ndih = k;
392
393   sfree(index);
394 }
395
396 static int get_impropers(t_atoms *atoms,t_hackblock hb[],t_param **idih,
397                          gmx_bool bAllowMissing)
398 {
399   char      *a0;
400   t_rbondeds *idihs;
401   t_rbonded  *hbidih;
402   int       nidih,i,j,k,r,start,ninc,nalloc;
403   atom_id   ai[MAXATOMLIST];
404   gmx_bool      bStop;
405   
406   ninc = 500;
407   nalloc = ninc;
408   snew(*idih,nalloc);
409
410   /* Add all the impropers from the residue database to the list. */
411   nidih = 0;
412   start = 0;
413   if (hb != NULL) {
414     for(i=0; (i<atoms->nres); i++) {
415       idihs=&hb[i].rb[ebtsIDIHS];
416       for(j=0; (j<idihs->nb); j++) {
417         bStop=FALSE;
418         for(k=0; (k<4) && !bStop; k++) {
419           ai[k] = search_atom(idihs->b[j].a[k],start,
420                           atoms,
421                               "improper",bAllowMissing);
422           if (ai[k] == NO_ATID)
423             bStop = TRUE;
424         }
425         if (!bStop) {
426           if (nidih == nalloc) {
427             nalloc += ninc;
428             srenew(*idih,nalloc);
429           }
430           /* Not broken out */
431           set_p(&((*idih)[nidih]),ai,NULL,idihs->b[j].s);
432           nidih++;
433         }
434       }
435       while ((start<atoms->nr) && (atoms->atom[start].resind == i))
436         start++;
437     }
438   }
439   
440   return nidih;
441 }
442
443 static int nb_dist(t_nextnb *nnb,int ai,int aj)
444 {
445   int nre,nrx,NRE;
446   int *nrexcl;
447   int *a;
448   
449   if (ai == aj)
450     return 0;
451   
452   NRE=-1;
453   nrexcl=nnb->nrexcl[ai];
454   for(nre=1; (nre < nnb->nrex); nre++) {
455     a=nnb->a[ai][nre];
456     for(nrx=0; (nrx < nrexcl[nre]); nrx++) {
457       if ((aj == a[nrx]) && (NRE == -1))
458         NRE=nre;
459     }
460   }
461   return NRE;
462 }
463
464 gmx_bool is_hydro(t_atoms *atoms,int ai)
465 {
466   return ((*(atoms->atomname[ai]))[0] == 'H');
467 }
468
469 static void get_atomnames_min(int n,char **anm,
470                               int resind,t_atoms *atoms,atom_id *a)
471 {
472   int m;
473
474   /* Assume ascending residue numbering */
475   for(m=0; m<n; m++) {
476     if (atoms->atom[a[m]].resind < resind)
477       strcpy(anm[m],"-");
478     else if (atoms->atom[a[m]].resind > resind)
479       strcpy(anm[m],"+");
480     else
481       strcpy(anm[m],"");
482     strcat(anm[m],*(atoms->atomname[a[m]]));
483   }
484 }
485
486 static void gen_excls(t_atoms *atoms, t_excls *excls, t_hackblock hb[],
487                       gmx_bool bAllowMissing)
488 {
489   int        r;
490   atom_id    a,astart,i1,i2,itmp;
491   t_rbondeds *hbexcl;
492   int        e;
493   char       *anm;
494
495   astart = 0;
496   for(a=0; a<atoms->nr; a++) {
497     r = atoms->atom[a].resind;
498     if (a==atoms->nr-1 || atoms->atom[a+1].resind != r) {
499       hbexcl = &hb[r].rb[ebtsEXCLS];
500       
501       for(e=0; e<hbexcl->nb; e++) {
502         anm = hbexcl->b[e].a[0];
503         i1 = search_atom(anm,astart,atoms,
504                          "exclusion",bAllowMissing);
505         anm = hbexcl->b[e].a[1];
506         i2 = search_atom(anm,astart,atoms,
507                          "exclusion",bAllowMissing);
508         if (i1!=NO_ATID && i2!=NO_ATID) {
509           if (i1 > i2) {
510             itmp = i1;
511             i1 = i2;
512             i2 = itmp;
513           }
514           srenew(excls[i1].e,excls[i1].nr+1);
515           excls[i1].e[excls[i1].nr] = i2;
516           excls[i1].nr++;
517         }
518       }
519       
520       astart = a+1;
521     }
522   }
523
524   for(a=0; a<atoms->nr; a++)
525     if (excls[a].nr > 1)
526       qsort(excls[a].e,excls[a].nr,(size_t)sizeof(atom_id),atom_id_comp);
527 }
528
529 static void remove_excl(t_excls *excls, int remove)
530 {
531   int i;
532
533   for(i=remove+1; i<excls->nr; i++)
534     excls->e[i-1] = excls->e[i];
535   
536   excls->nr--;
537 }
538
539 void clean_excls(t_nextnb *nnb, int nrexcl, t_excls excls[])
540 {
541   int i,j,j1,k,k1,l,l1,m,n,e;
542   t_excls *excl;
543
544   if (nrexcl >= 1)
545     /* extract all i-j-k-l neighbours from nnb struct */
546     for(i=0; (i<nnb->nr); i++) {
547       /* For all particles */
548       excl = &excls[i];
549       
550       for(j=0; (j<nnb->nrexcl[i][1]); j++) {
551         /* For all first neighbours */
552         j1=nnb->a[i][1][j];
553         
554         for(e=0; e<excl->nr; e++)
555           if (excl->e[e] == j1)
556             remove_excl(excl,e);
557         
558         if (nrexcl >= 2)
559           for(k=0; (k<nnb->nrexcl[j1][1]); k++) {
560             /* For all first neighbours of j1 */
561             k1=nnb->a[j1][1][k];
562           
563             for(e=0; e<excl->nr; e++)
564               if (excl->e[e] == k1)
565                 remove_excl(excl,e);
566             
567             if (nrexcl >= 3)
568               for(l=0; (l<nnb->nrexcl[k1][1]); l++) {
569                 /* For all first neighbours of k1 */
570                 l1=nnb->a[k1][1][l];
571
572                 for(e=0; e<excl->nr; e++)
573                   if (excl->e[e] == l1)
574                     remove_excl(excl,e);
575               }
576           }
577       }
578     }
579 }
580
581 void generate_excls(t_nextnb *nnb, int nrexcl, t_excls excls[])
582 {
583   int i,j,j1,k,k1,l,l1,m,n,e,N;
584   t_excls *excl;
585
586   for(N=1; (N<min(nrexcl,nnb->nrex)); N++) {
587     /* extract all i-j-k-l neighbours from nnb struct */
588     for(i=0; (i<nnb->nr); i++) {
589       /* For all particles */
590       excl = &excls[i];
591       n = excl->nr;
592       excl->nr += nnb->nrexcl[i][N];
593       srenew(excl->e,excl->nr);
594       for(j=0; (j<nnb->nrexcl[i][N]); j++) 
595         /* For all first neighbours */
596         if (nnb->a[i][N][j] != i)
597           excl->e[n++] = nnb->a[i][N][j];
598     }
599   }
600 }
601
602 void gen_pad(t_nextnb *nnb, t_atoms *atoms, int nrexcl, gmx_bool bH14,
603              t_params plist[], t_excls excls[], t_hackblock hb[], 
604              gmx_bool bAlldih, gmx_bool bRemoveDih, gmx_bool bAllowMissing)
605 {
606   t_param *ang,*dih,*pai,*idih;
607   t_rbondeds *hbang, *hbdih;
608   char    **anm;
609   int     res,minres,maxres;
610   int     i,j,j1,k,k1,l,l1,m,n,i1,i2;
611   int     ninc,maxang,maxdih,maxpai;
612   int     nang,ndih,npai,nidih,nbd;
613   int     nFound;
614   gmx_bool    bFound,bExcl;
615   
616
617   /* These are the angles, dihedrals and pairs that we generate
618    * from the bonds. The ones that are already there from the rtp file
619    * will be retained.
620    */
621   nang   = 0;
622   npai   = 0;
623   ndih   = 0;
624   ninc   = 500;
625   maxang = maxdih = maxpai = ninc;
626   snew(ang, maxang);
627   snew(dih, maxdih);
628   snew(pai, maxpai);
629
630   snew(anm,4);
631   for(i=0;i<4;i++)
632     snew(anm[i],12);
633
634   if (hb)
635     gen_excls(atoms,excls,hb,bAllowMissing);
636   
637   /* extract all i-j-k-l neighbours from nnb struct */
638   for(i=0; (i<nnb->nr); i++) 
639     /* For all particles */
640     for(j=0; (j<nnb->nrexcl[i][1]); j++) {
641       /* For all first neighbours */
642       j1=nnb->a[i][1][j];
643       for(k=0; (k<nnb->nrexcl[j1][1]); k++) {
644         /* For all first neighbours of j1 */
645         k1=nnb->a[j1][1][k];
646         if (k1 != i) {
647           /* Generate every angle only once */
648           if (i < k1) {
649             if (nang == maxang) {
650               maxang += ninc;
651               srenew(ang,maxang);
652             }
653             ang[nang].AI=i;
654             ang[nang].AJ=j1;
655             ang[nang].AK=k1;
656             ang[nang].C0=NOTSET;
657             ang[nang].C1=NOTSET;
658             set_p_string(&(ang[nang]),"");
659             if (hb) {
660               minres = atoms->atom[ang[nang].a[0]].resind;
661               maxres = minres;
662               for(m=1; m<3; m++) {
663                 minres = min(minres,atoms->atom[ang[nang].a[m]].resind);
664                 maxres = max(maxres,atoms->atom[ang[nang].a[m]].resind);
665               }
666               res = 2*minres-maxres;
667               do {
668                 res += maxres-minres;
669                 get_atomnames_min(3,anm,res,atoms,ang[nang].a);
670                 hbang=&hb[res].rb[ebtsANGLES];
671                 for(l=0; (l<hbang->nb); l++) {
672                   if (strcmp(anm[1],hbang->b[l].AJ)==0) {
673                     bFound=FALSE;
674                     for (m=0; m<3; m+=2)
675                       bFound=(bFound ||
676                               ((strcmp(anm[m],hbang->b[l].AI)==0) &&
677                                (strcmp(anm[2-m],hbang->b[l].AK)==0)));
678                     if (bFound) {
679                       set_p_string(&(ang[nang]),hbang->b[l].s);
680                     }
681                   }
682                 }
683               } while (res < maxres);
684             }
685             nang++;
686           }
687           /* Generate every dihedral, 1-4 exclusion and 1-4 interaction
688              only once */
689           if (j1 < k1) {
690             for(l=0; (l<nnb->nrexcl[k1][1]); l++) {
691               /* For all first neighbours of k1 */
692               l1=nnb->a[k1][1][l];
693               if ((l1 != i) && (l1 != j1)) {
694                 if (ndih == maxdih) {
695                   maxdih += ninc;
696                   srenew(dih,maxdih);
697                 }
698                 dih[ndih].AI=i;
699                 dih[ndih].AJ=j1;
700                 dih[ndih].AK=k1;
701                 dih[ndih].AL=l1;
702                 for (m=0; m<MAXFORCEPARAM; m++)
703                   dih[ndih].c[m]=NOTSET;
704                 set_p_string(&(dih[ndih]),"");
705                 nFound = 0;
706                 if (hb) {
707                   minres = atoms->atom[dih[ndih].a[0]].resind;
708                   maxres = minres;
709                   for(m=1; m<4; m++) {
710                     minres = min(minres,atoms->atom[dih[ndih].a[m]].resind);
711                     maxres = max(maxres,atoms->atom[dih[ndih].a[m]].resind);
712                   }
713                   res = 2*minres-maxres;
714                   do {
715                     res += maxres-minres;
716                     get_atomnames_min(4,anm,res,atoms,dih[ndih].a);
717                     hbdih=&hb[res].rb[ebtsPDIHS];
718                     for(n=0; (n<hbdih->nb); n++) {
719                       bFound=FALSE;
720                       for (m=0; m<2; m++)
721                         bFound=(bFound ||
722                                 ((strcmp(anm[3*m],  hbdih->b[n].AI)==0) &&
723                                  (strcmp(anm[1+m],  hbdih->b[n].AJ)==0) &&
724                                  (strcmp(anm[2-m],  hbdih->b[n].AK)==0) &&
725                                  (strcmp(anm[3-3*m],hbdih->b[n].AL)==0)));
726                       if (bFound) {
727                         set_p_string(&dih[ndih],hbdih->b[n].s);
728                         
729                         /* Set the last parameter to be able to see
730                            if the dihedral was in the rtp list.
731                            */
732                         dih[ndih].c[MAXFORCEPARAM-1] = 0;
733                         nFound++;
734                         ndih++;
735                         /* Set the next direct in case the rtp contains
736                            multiple entries for this dihedral.
737                            */
738                         if (ndih == maxdih) {
739                           maxdih += ninc;
740                           srenew(dih,maxdih);
741                         }
742                         dih[ndih].AI=i;
743                         dih[ndih].AJ=j1;
744                         dih[ndih].AK=k1;
745                         dih[ndih].AL=l1;
746                         for (m=0; m<MAXFORCEPARAM; m++)
747                           dih[ndih].c[m]=NOTSET;
748                       }
749                     }
750                   } while (res < maxres);
751                 }
752                 if (nFound == 0) {
753                   if (ndih == maxdih) {
754                     maxdih += ninc;
755                     srenew(dih,maxdih);
756                   }
757                   dih[ndih].AI=i;
758                   dih[ndih].AJ=j1;
759                   dih[ndih].AK=k1;
760                   dih[ndih].AL=l1;
761                   for (m=0; m<MAXFORCEPARAM; m++)
762                     dih[ndih].c[m]=NOTSET;
763                   set_p_string(&(dih[ndih]),"");
764                   ndih++;
765                 }
766
767                 nbd=nb_dist(nnb,i,l1);
768                 if (debug)
769                   fprintf(debug,"Distance (%d-%d) = %d\n",i+1,l1+1,nbd);
770                 if (nbd == 3) {
771                   i1 = min(i,l1);
772                   i2 = max(i,l1);
773                   bExcl = FALSE;
774                   for(m=0; m<excls[i1].nr; m++)
775                     bExcl = bExcl || excls[i1].e[m]==i2;
776                   if (!bExcl) {
777                     if (bH14 || !(is_hydro(atoms,i1) && is_hydro(atoms,i2))) {
778                       if (npai == maxpai) {
779                         maxpai += ninc;
780                         srenew(pai,maxpai);
781                       }
782                       pai[npai].AI=i1;
783                       pai[npai].AJ=i2;
784                       pai[npai].C0=NOTSET;
785                       pai[npai].C1=NOTSET;
786                       set_p_string(&(pai[npai]),"");
787                       npai++;
788                     }
789                   }
790                 }
791               }
792             }
793           }
794         }
795       }
796     }
797
798   /* Sort angles with respect to j-i-k (middle atom first) */
799   if (nang > 1)
800     qsort(ang,nang,(size_t)sizeof(ang[0]),acomp);
801   
802   /* Sort dihedrals with respect to j-k-i-l (middle atoms first) */
803   if (ndih > 1)
804     qsort(dih,ndih,(size_t)sizeof(dih[0]),dcomp);
805   
806   /* Sort the pairs */
807   if (npai > 1)
808     qsort(pai,npai,(size_t)sizeof(pai[0]),pcomp);
809   if (npai > 0) {
810     /* Remove doubles, could occur in 6-rings, such as phenyls,
811        maybe one does not want this when fudgeQQ < 1.
812        */
813     fprintf(stderr,"Before cleaning: %d pairs\n",npai);
814     rm2par(pai,&npai,preq);
815   }
816
817   /* Get the impropers from the database */
818   nidih = get_impropers(atoms,hb,&idih,bAllowMissing);
819
820   /* Sort the impropers */
821   sort_id(nidih,idih);
822  
823   if (ndih > 0) {
824     /* Remove dihedrals which are impropers
825        and when bAlldih is not set remove multiple dihedrals over one bond.
826        */
827     fprintf(stderr,"Before cleaning: %d dihedrals\n",ndih);
828     clean_dih(dih,&ndih,idih,nidih,atoms,bAlldih,bRemoveDih);
829   }
830
831   /* Now we have unique lists of angles and dihedrals 
832    * Copy them into the destination struct
833    */
834   cppar(ang, nang, plist,F_ANGLES);
835   cppar(dih, ndih, plist,F_PDIHS);
836   cppar(idih,nidih,plist,F_IDIHS);
837   cppar(pai, npai, plist,F_LJ14);
838
839   /* Remove all exclusions which are within nrexcl */
840   clean_excls(nnb,nrexcl,excls);
841
842   sfree(ang);
843   sfree(dih);
844   sfree(idih);
845   sfree(pai);
846 }
847