4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * GRowing Old MAkes el Chrono Sweat
29 static char *SRCID_gen_ad_c
= "$Id$";
49 typedef bool (*peq
)(t_param
*p1
, t_param
*p2
);
51 static int acomp(const void *a1
, const void *a2
)
58 if ((ac
=(p1
->AJ
-p2
->AJ
))!=0)
60 else if ((ac
=(p1
->AI
-p2
->AI
))!=0)
63 return (p1
->AK
-p2
->AK
);
66 static int pcomp(const void *a1
, const void *a2
)
73 if ((pc
=(p1
->AI
-p2
->AI
))!=0)
76 return (p1
->AJ
-p2
->AJ
);
79 static int dcomp(const void *d1
, const void *d2
)
86 if ((dc
=(p1
->AJ
-p2
->AJ
))!=0)
88 else if ((dc
=(p1
->AK
-p2
->AK
))!=0)
90 else if ((dc
=(p1
->AI
-p2
->AI
))!=0)
93 return (p1
->AL
-p2
->AL
);
96 static bool aeq(t_param
*p1
, t_param
*p2
)
100 else if (((p1
->AI
==p2
->AI
) && (p1
->AK
==p2
->AK
)) ||
101 ((p1
->AI
==p2
->AK
) && (p1
->AK
==p2
->AI
)))
107 static bool deq2(t_param
*p1
, t_param
*p2
)
109 /* if bAlldih is true, dihedrals are only equal when
110 ijkl = ijkl or ijkl =lkji*/
111 if (((p1
->AI
==p2
->AI
) && (p1
->AJ
==p2
->AJ
) &&
112 (p1
->AK
==p2
->AK
) && (p1
->AL
==p2
->AL
)) ||
113 ((p1
->AI
==p2
->AL
) && (p1
->AJ
==p2
->AK
) &&
114 (p1
->AK
==p2
->AJ
) && (p1
->AL
==p2
->AI
)))
120 static bool deq(t_param
*p1
, t_param
*p2
)
122 if (((p1
->AJ
==p2
->AJ
) && (p1
->AK
==p2
->AK
)) ||
123 ((p1
->AJ
==p2
->AK
) && (p1
->AK
==p2
->AJ
)))
129 static bool remove_dih(t_param
*p
, int i
, int np
)
130 /* check if dihedral p[i] should be removed */
136 bMidEq
= deq(&p
[i
],&p
[i
-1]);
140 if (p
[i
].c
[MAXFORCEPARAM
-1]==NOTSET
) {
141 /* also remove p[i] if there is a dihedral on the same bond
142 which has parameters set */
145 while (!bRem
&& (j
<np
) && deq(&p
[i
],&p
[j
])) {
146 bRem
= (p
[j
].c
[MAXFORCEPARAM
-1] != NOTSET
);
150 bRem
= bMidEq
&& (((p
[i
].AI
==p
[i
-1].AI
) && (p
[i
].AL
==p
[i
-1].AL
)) ||
151 ((p
[i
].AI
==p
[i
-1].AL
) && (p
[i
].AL
==p
[i
-1].AI
)));
156 static bool preq(t_param
*p1
, t_param
*p2
)
158 if ((p1
->AI
==p2
->AI
) && (p1
->AJ
==p2
->AJ
))
164 static void rm2par(t_param p
[], int *np
, peq eq
)
175 for(i
=1; (i
<(*np
)); i
++)
176 if (!eq(&p
[i
],&p
[i
-1]))
178 /* Index now holds pointers to all the non-equal params,
179 * this only works when p is sorted of course
181 for(i
=0; (i
<nind
); i
++) {
182 for(j
=0; (j
<MAXATOMLIST
); j
++)
183 p
[i
].a
[j
]=p
[index
[i
]].a
[j
];
184 for(j
=0; (j
<MAXFORCEPARAM
); j
++)
185 p
[i
].c
[j
]=p
[index
[i
]].c
[j
];
186 if (p
[index
[i
]].a
[0] == p
[index
[i
]].a
[1]) {
189 "Something VERY strange is going on in rm2par (gen_ad.c)\n"
190 "a[0] %u a[1] %u a[2] %u a[3] %u\n",
191 p
[i
].a
[0],p
[i
].a
[1],p
[i
].a
[2],p
[i
].a
[3]);
193 } else if (index
[i
] > i
) {
194 /* Copy the string only if it comes from somewhere else
195 * otherwise we will end up copying a random (newly freed) pointer.
196 * Since the index is sorted we only have to test for index[i] > i.
199 p
[i
].s
= strdup(p
[index
[i
]].s
);
207 static void cppar(t_param p
[], int np
, t_params plist
[], int ftype
)
218 for(i
=0; (i
<np
); i
++) {
219 for(j
=0; (j
<nral
); j
++)
220 ps
->param
[ps
->nr
].a
[j
] = p
[i
].a
[j
];
221 for(j
=0; (j
<nrfp
); j
++)
222 ps
->param
[ps
->nr
].c
[j
] = p
[i
].c
[j
];
223 ps
->param
[ps
->nr
].s
=strdup(p
[i
].s
);
228 static void cpparam(t_param
*dest
, t_param
*src
)
232 for(j
=0; (j
<MAXATOMLIST
); j
++)
233 dest
->a
[j
]=src
->a
[j
];
234 for(j
=0; (j
<MAXFORCEPARAM
); j
++)
235 dest
->c
[j
]=src
->c
[j
];
236 dest
->s
=strdup(src
->s
);
239 static void set_p(t_param
*p
, atom_id ai
[4], real
*c
, char *s
)
245 for(j
=0; (j
<MAXFORCEPARAM
); j
++)
257 static int int_comp(const void *a
,const void *b
)
259 return (*(int *)a
) - (*(int *)b
);
262 static int eq_imp(atom_id a1
[],atom_id a2
[])
267 for(j
=0; (j
<4); j
++) {
271 qsort(b1
,4,(size_t)sizeof(b1
[0]),int_comp
);
272 qsort(b2
,4,(size_t)sizeof(b2
[0]),int_comp
);
281 static bool ideq(t_param
*p1
, t_param
*p2
)
283 return eq_imp(p1
->a
,p2
->a
);
286 static int idcomp(const void *a
,const void *b
)
293 if ((d
=(pa
->a
[0]-pb
->a
[0])) != 0)
295 else if ((d
=(pa
->a
[3]-pb
->a
[3])) != 0)
297 else if ((d
=(pa
->a
[1]-pb
->a
[1])) != 0)
300 return (int) (pa
->a
[2]-pb
->a
[2]);
303 static void sort_id(int nr
,t_param ps
[])
305 qsort(ps
,nr
,(size_t)sizeof(ps
[0]),idcomp
);
308 static t_rbonded
*is_imp(t_param
*p
,t_atoms
*atoms
,t_hackblock hb
[])
310 int j
,n
,maxresnr
,start
;
311 atom_id aa0
,a0
[MAXATOMLIST
];
317 /* Find the max residue number in this dihedral */
320 maxresnr
=max(maxresnr
,atoms
->atom
[p
->a
[j
]].resnr
);
322 /* Now find the start of this residue */
323 for(start
=0; start
< atoms
->nr
; start
++)
324 if (atoms
->atom
[start
].resnr
== maxresnr
)
327 /* See if there are any impropers defined for this residue */
328 idihs
= &hb
[atoms
->atom
[start
].resnr
].rb
[ebtsIDIHS
];
329 for(n
=0; n
< idihs
->nb
; n
++) {
330 for(j
=0; (j
<4); j
++) {
331 atom
=idihs
->b
[n
].a
[j
];
332 aa0
=search_atom(atom
,start
,atoms
->nr
,atoms
->atom
,atoms
->atomname
);
333 if (aa0
== NO_ATID
) {
335 fprintf(debug
,"Atom %s not found in res %d (maxresnr=%d) "
336 "in is_imp\n",atom
,atoms
->atom
[start
].resnr
,maxresnr
);
341 if (j
==4) /* Not broken out */
348 static int n_hydro(atom_id a
[],char ***atomname
)
353 for(i
=0; (i
<4); i
+=3) {
354 aname
=*atomname
[a
[i
]];
355 c0
=toupper(aname
[0]);
358 else if (((int)strlen(aname
) > 1) && (c0
>= '0') && (c0
<= '9')) {
359 c1
=toupper(aname
[1]);
367 static void pdih2idih(t_param
*alldih
, int *nalldih
,t_param idih
[],int *nidih
,
368 t_atoms
*atoms
, t_hackblock hb
[],bool bAlldih
)
375 int i
,j
,k
,l
,start
,aa0
;
377 atom_id ai
[MAXATOMLIST
];
378 bool bStop
,bIsSet
,bKeep
;
381 /* First add all the impropers from the residue database
386 for(i
=0; (i
<atoms
->nres
); i
++) {
387 idihs
=&hb
[i
].rb
[ebtsIDIHS
];
388 for(j
=0; (j
<idihs
->nb
); j
++) {
390 for(k
=0; (k
<4) && !bStop
; k
++) {
391 ai
[k
]=search_atom(idihs
->b
[j
].a
[k
],start
,
392 atoms
->nr
,atoms
->atom
,atoms
->atomname
);
393 if (ai
[k
] == NO_ATID
) {
395 fprintf(debug
,"Atom %s (%d) not found in res %d in pdih2idih\n",
396 idihs
->b
[j
].a
[k
], k
, atoms
->atom
[start
].resnr
);
402 set_p(&idih
[*nidih
],ai
,NULL
,idihs
->b
[j
].s
);
406 while ((start
<atoms
->nr
) && (atoms
->atom
[start
].resnr
==i
))
413 /* Copy the impropers and dihedrals to seperate arrays. */
416 for(i
=0; i
<*nalldih
; i
++) {
417 hbidih
= is_imp(&alldih
[i
],atoms
,hb
);
419 set_p(&idih
[*nidih
],alldih
[i
].a
,NULL
,hbidih
->s
);
422 cpparam(&dih
[ndih
],&alldih
[i
]);
427 /* Now, because this list still contains the double entries,
428 * keep the dihedral with parameters or the first one.
434 fprintf(stderr
,"bAlldih = true\n");
435 for(i
=0; i
<ndih
; i
++)
436 if ((i
==0) || !deq2(&dih
[i
],&dih
[i
-1]))
439 for(i
=0; i
<ndih
; i
++)
440 if (!remove_dih(dih
,i
,ndih
))
445 /* if we don't want all dihedrals, we need to select the ones with the
450 for(i
=0; i
<nind
; i
++) {
451 bIsSet
= (dih
[index
[i
]].c
[MAXFORCEPARAM
-1] != NOTSET
);
454 /* remove the dihedral if there is an improper on the same bond */
455 for(j
=0; (j
<(*nidih
)) && bKeep
; j
++)
456 bKeep
= !deq(&dih
[index
[i
]],&idih
[j
]);
459 /* Now select the "fittest" dihedral:
460 * the one with as few hydrogens as possible
463 /* Best choice to get dihedral from */
465 if (!bAlldih
&& !bIsSet
) {
466 /* Minimum number of hydrogens for i and l atoms */
468 for(l
=index
[i
]; (l
<index
[i
+1]) && deq(&dih
[index
[i
]],&dih
[l
]); l
++) {
469 if ((nh
=n_hydro(dih
[l
].a
,atoms
->atomname
)) < minh
) {
477 for(j
=0; (j
<MAXATOMLIST
); j
++)
478 alldih
[k
].a
[j
] = dih
[bestl
].a
[j
];
479 for(j
=0; (j
<MAXFORCEPARAM
); j
++)
480 alldih
[k
].c
[j
] = dih
[bestl
].c
[j
];
482 alldih
[k
].s
= strdup(dih
[bestl
].s
);
486 for (i
=k
; i
< *nalldih
; i
++)
490 for(i
=0; i
<ndih
; i
++)
496 static int nb_dist(t_nextnb
*nnb
,int ai
,int aj
)
506 nrexcl
=nnb
->nrexcl
[ai
];
507 for(nre
=1; (nre
< nnb
->nrex
); nre
++) {
509 for(nrx
=0; (nrx
< nrexcl
[nre
]); nrx
++) {
510 if ((aj
== a
[nrx
]) && (NRE
== -1))
517 bool is_hydro(t_atoms
*atoms
,int ai
)
519 return ((*(atoms
->atomname
[ai
]))[0] == 'H');
522 static void get_atomnames_min(int n
,char anm
[4][12],
523 int res
,t_atoms
*atoms
,atom_id
*a
)
527 /* Assume ascending residue numbering */
529 if (atoms
->atom
[a
[m
]].resnr
< res
)
531 else if (atoms
->atom
[a
[m
]].resnr
> res
)
535 strcat(anm
[m
],*(atoms
->atomname
[a
[m
]]));
539 void gen_pad(t_nextnb
*nnb
, t_atoms
*atoms
, bool bH14
,
540 t_params plist
[], t_hackblock hb
[], bool bAlldih
)
542 t_param
*ang
,*dih
,*pai
,*idih
;
543 t_rbondeds
*hbang
, *hbdih
;
545 int res
,minres
,maxres
;
546 int i
,j
,j1
,k
,k1
,l
,l1
,m
,n
;
547 int maxang
,maxdih
,maxidih
,maxpai
;
548 int nang
,ndih
,npai
,nidih
,nbd
;
552 /* These are the angles, pairs, impropers and dihedrals that we generate
553 * from the bonds. The ones that are already there from the rtp file
563 maxdih
= maxpai
= maxidih
= ddih
;
569 /* extract all i-j-k-l neighbours from nnb struct */
570 for(i
=0; (i
<nnb
->nr
); i
++)
571 /* For all particles */
572 for(j
=0; (j
<nnb
->nrexcl
[i
][1]); j
++) {
573 /* For all first neighbours */
575 for(k
=0; (k
<nnb
->nrexcl
[j1
][1]); k
++) {
576 /* For all first neighbours of j1 */
579 if (nang
== maxang
) {
580 srenew(ang
,maxang
+dang
);
581 memset(ang
+maxang
,0,sizeof(ang
[0]));
595 ang
[nang
].s
=strdup("");
597 minres
= atoms
->atom
[ang
[nang
].a
[0]].resnr
;
600 minres
= min(minres
,atoms
->atom
[ang
[nang
].a
[m
]].resnr
);
601 maxres
= max(maxres
,atoms
->atom
[ang
[nang
].a
[m
]].resnr
);
603 res
= 2*minres
-maxres
;
605 res
+= maxres
-minres
;
606 hbang
=&hb
[res
].rb
[ebtsANGLES
];
607 for(l
=0; (l
<hbang
->nb
); l
++) {
608 get_atomnames_min(3,anm
,res
,atoms
,ang
[nang
].a
);
609 if (strcmp(anm
[1],hbang
->b
[l
].AJ
)==0) {
613 ((strcmp(anm
[m
],hbang
->b
[l
].AI
)==0) &&
614 (strcmp(anm
[2-m
],hbang
->b
[l
].AK
)==0)));
618 ang
[nang
].s
= strdup(hbang
->b
[l
].s
);
620 ang
[nang
].s
= strdup("");
624 } while (res
< maxres
);
627 for(l
=0; (l
<nnb
->nrexcl
[k1
][1]); l
++) {
628 /* For all first neighbours of k1 */
630 if ((l1
!= i
) && (l1
!= j1
)) {
631 if (ndih
== maxdih
) {
632 srenew(dih
,maxdih
+ddih
);
633 memset(dih
+maxdih
,0,sizeof(dih
[0]));
634 srenew(idih
,maxdih
+ddih
);
635 memset(idih
+maxdih
,0,sizeof(idih
[0]));
636 srenew(pai
,maxdih
+ddih
);
637 memset(pai
+maxdih
,0,sizeof(pai
[0]));
652 for (m
=0; m
<MAXFORCEPARAM
; m
++)
653 dih
[ndih
].c
[m
]=NOTSET
;
654 dih
[ndih
].s
=strdup("");
656 minres
= atoms
->atom
[dih
[ndih
].a
[0]].resnr
;
659 minres
= min(minres
,atoms
->atom
[dih
[ndih
].a
[m
]].resnr
);
660 maxres
= max(maxres
,atoms
->atom
[dih
[ndih
].a
[m
]].resnr
);
662 res
= 2*minres
-maxres
;
664 res
+= maxres
-minres
;
665 hbdih
=&hb
[res
].rb
[ebtsPDIHS
];
666 for(n
=0; (n
<hbdih
->nb
); n
++) {
667 get_atomnames_min(4,anm
,res
,atoms
,dih
[ndih
].a
);
671 ((strcmp(anm
[3*m
], hbdih
->b
[n
].AI
)==0) &&
672 (strcmp(anm
[1+m
], hbdih
->b
[n
].AJ
)==0) &&
673 (strcmp(anm
[2-m
], hbdih
->b
[n
].AK
)==0) &&
674 (strcmp(anm
[3-3*m
],hbdih
->b
[n
].AL
)==0)));
678 dih
[ndih
].s
= strdup(hbdih
->b
[n
].s
);
680 dih
[ndih
].s
= strdup("");
681 /* Set the last parameter to be able to see
682 if the dihedral was in the rtp list */
683 dih
[ndih
].c
[MAXFORCEPARAM
-1] = 0;
686 } while (res
< maxres
);
688 nbd
=nb_dist(nnb
,i
,l1
);
690 fprintf(debug
,"Distance (%d-%d) = %d\n",i
+1,l1
+1,nbd
);
692 pai
[npai
].AI
=min(i
,l1
);
693 pai
[npai
].AJ
=max(i
,l1
);
697 pai
[npai
].s
=strdup("");
698 if (bH14
|| !(is_hydro(atoms
,pai
[npai
].AI
) &&
699 is_hydro(atoms
,pai
[npai
].AJ
)))
710 /* We now have a params list with double entries for each angle,
711 * and even more for each dihedral. We will remove these now.
713 /* Sort angles with respect to j-i-k (middle atom first) */
714 qsort(ang
,nang
,(size_t)sizeof(ang
[0]),acomp
);
715 rm2par(ang
,&nang
,aeq
);
717 /* Sort dihedrals with respect to j-k-i-l (middle atoms first) */
718 fprintf(stderr
,"before sorting: %d dihedrals\n",ndih
);
719 qsort(dih
,ndih
,(size_t)sizeof(dih
[0]),dcomp
);
720 pdih2idih(dih
,&ndih
,idih
,&nidih
,atoms
,hb
,bAlldih
);
721 fprintf(stderr
,"after sorting: %d dihedrals\n",ndih
);
723 /* Now the dihedrals are sorted and doubles removed, this has to be done
727 rm2par(idih
,&nidih
,ideq
);
729 /* And for the pairs */
730 fprintf(stderr
,"There are %d pairs before sorting\n",npai
);
731 qsort(pai
,npai
,(size_t)sizeof(pai
[0]),pcomp
);
732 rm2par(pai
,&npai
,preq
);
734 /* Now we have unique lists of angles and dihedrals
735 * Copy them into the destination struct
737 cppar(ang
, nang
, plist
,F_ANGLES
);
738 cppar(dih
, ndih
, plist
,F_PDIHS
);
739 cppar(idih
,nidih
,plist
,F_IDIHS
);
740 cppar(pai
, npai
, plist
,F_LJ14
);
743 for(i
=0; i
<nang
; i
++)
747 for(i
=0; i
<ndih
; i
++)
751 for(i
=0; i
<nidih
; i
++)
755 for(i
=0; i
<npai
; i
++)