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_bondlist_c
= "$Id$";
46 static bondlist
*lst
=NULL
;
48 static void newresidue(char *residue
)
53 p
->residue
= strdup(residue
);
61 fprintf(debug
,"initialised element for residue %s\n",residue
);
64 void read_O_dist(void)
67 static char *fn
= "refi_aa.dat";
69 char buf
[BLEN
+1],buf_ai
[9],buf_aj
[9],junk1
[15],junk2
[15];
74 fprintf(stderr
,"Going to read %s\n",fn
);
75 fprintf(stderr
,"Take note that the angle O C N+ will not be read from the");
76 fprintf(stderr
," correct residue\nThis is not a problem in the current");
77 fprintf(stderr
,"(980927) param-file while \nthis angle is const. 123.000\n");
78 while (fgets2(buf
,BLEN
,fp
) != NULL
) {
86 sscanf(buf
,"%s%s",buf_ai
,buf_aj
);
87 if (strcmp(buf_ai
,"residue") == 0 ) {
89 /* O only uses HIS, Gromos has HISB... */
90 if (strcmp(buf_aj
,"HIS") == 0) strcpy(buf_aj
,"HISB");
95 if ( buf
[5] == 'd' ) {
96 sscanf(buf
,"%*s%s%s%lf",buf_ai
,buf_aj
,&dist
);
97 /*fprintf(stderr,"1: %s %s %g\n",buf_ai,buf_aj,dist);*/
98 if (strcmp(buf_ai
,"C-") == 0) strcpy(buf_ai
,"C");
99 if (strcmp(buf_ai
,"CA-") == 0) strcpy(buf_ai
,"CA");
100 if (strcmp(buf_ai
,"N+") == 0) strcpy(buf_ai
,"N");
101 if (strcmp(buf_aj
,"C-") == 0) strcpy(buf_aj
,"C");
102 if (strcmp(buf_aj
,"CA-") == 0) strcpy(buf_aj
,"CA");
103 if (strcmp(buf_aj
,"N+") == 0) strcpy(buf_aj
,"N");
104 /*fprintf(stderr,"2: %s %s %g\n",buf_ai,buf_aj,dist);*/
106 lst
->atombond
= srenew(lst
->atombond
,lst
->natombond
);
107 lst
->atombond
[lst
->natombond
-1].ai
= strdup(buf_ai
);
108 lst
->atombond
[lst
->natombond
-1].aj
= strdup(buf_aj
);
109 lst
->atombond
[lst
->natombond
-1].dist
= (dist
/10.0);
111 if ( buf
[5] == 'a' ) {
112 sscanf(buf
,"%*s%s%*s%s%lf",buf_ai
,buf_aj
,&dist
);
113 /*fprintf(stderr,"1: %s %s %g\n",buf_ai,buf_aj,dist);*/
114 if (strcmp(buf_ai
,"C-") == 0) strcpy(buf_ai
,"C");
115 if (strcmp(buf_ai
,"CA-") == 0) strcpy(buf_ai
,"CA");
116 if (strcmp(buf_ai
,"N+") == 0) strcpy(buf_ai
,"N");
117 if (strcmp(buf_aj
,"C-") == 0) strcpy(buf_aj
,"C");
118 if (strcmp(buf_aj
,"CA-") == 0) strcpy(buf_aj
,"CA");
119 if (strcmp(buf_aj
,"N+") == 0) strcpy(buf_aj
,"N");
120 /*fprintf(stderr,"2: %s %s %g\n",buf_ai,buf_aj,dist);*/
122 lst
->atomangle
= srenew(lst
->atomangle
,lst
->natomangle
);
123 lst
->atomangle
[lst
->natomangle
-1].ai
= strdup(buf_ai
);
124 lst
->atomangle
[lst
->natomangle
-1].aj
= strdup(buf_aj
);
125 lst
->atomangle
[lst
->natomangle
-1].angle
= dist
;
129 fprintf(stderr
,"Ooops! Unexpected first character in line:\n%s",buf
);
135 fprintf(stderr
,"Read distances for %d residues from file %s \n",nres
,fn
);
138 static real
do_specialbond(char *name1
,char *name2
,char *res
)
144 fprintf(debug
,"Looking for dist between %s %s in res. %s\n",
147 for ( p
= lst
; p
!= NULL
; p
= p
->next
)
148 if (strcmp(res
,p
->residue
) == 0)
151 /* Here either p == NULL or found */
152 for (i
=0; p
!= NULL
&& (i
<p
->natombond
) ; i
++) {
153 if (((strcmp(name1
,p
->atombond
[i
].ai
) == 0) &&
154 (strcmp(name2
,p
->atombond
[i
].aj
) == 0)) ||
155 ((strcmp(name1
,p
->atombond
[i
].aj
) == 0) &&
156 (strcmp(name2
,p
->atombond
[i
].ai
) == 0))) {
158 fprintf(debug
,"Found dist. %s %s %s",name1
,name2
,res
);
159 fprintf(debug
," %g\n",p
->atombond
[i
].dist
);
161 return p
->atombond
[i
].dist
;
165 fprintf(debug
,"Didn't find dist. %s %s %s\n",name1
,name2
,res
);
170 static real
do_specialangle(char *name1
,char *name2
,char *res
)
177 fprintf(debug
,"Looking for angle between %s %s in res. %s\n",
180 for ( p
= lst
; p
!= NULL
; p
= p
->next
)
181 if (strcmp(res
,p
->residue
) == 0)
184 /* Here either p == NULL or found */
185 for (i
=0; p
!= NULL
&& (i
<p
->natomangle
) ; i
++) {
186 if (((strcmp(name1
,p
->atomangle
[i
].ai
) == 0) &&
187 (strcmp(name2
,p
->atomangle
[i
].aj
) == 0)) ||
188 ((strcmp(name1
,p
->atomangle
[i
].aj
) == 0) &&
189 (strcmp(name2
,p
->atomangle
[i
].ai
) == 0))) {
191 fprintf(debug
,"Found angle. %s %s %s",name1
,name2
,res
);
192 fprintf(debug
," %g\n",p
->atomangle
[i
].angle
);
194 return p
->atomangle
[i
].angle
;
198 fprintf(debug
,"Didn't find angle %s %s %s\n",name1
,name2
,res
);
203 real
lookup_bondlength(int ai
,int aj
,t_ilist ilist
[],
204 t_iparams iparams
[],bool bFail
,t_atoms
*atoms
)
206 int dodist
[] = { F_BONDS
, F_MORSE
, F_SHAKE
, F_G96BONDS
};
207 int i
,j
,type
,ftype
,aai
,aaj
,nra
;
212 fprintf(debug
,"call do_spec with %s (%d) %s (%d) res %s \n",
213 *atoms
->atomname
[ai
],ai
,*atoms
->atomname
[aj
],aj
,
214 *(atoms
->resname
[atoms
->atom
[ai
].resnr
]));
216 spclen
= do_specialbond(*(atoms
->atomname
[ai
]),*(atoms
->atomname
[aj
]),
217 *(atoms
->resname
[atoms
->atom
[aj
].resnr
]));
219 /* Comment; if you're using distances from e.g. O, it is non-trivial
220 which residuename (ai or aj) you call do_special with, in order
221 to get the peptide bonds correct. */
224 fprintf(debug
,"%s %d %d %g\n",*atoms
->resname
[atoms
->atom
[ai
].resnr
],
230 fprintf(debug
,"No spclen found for %s (%d) %s (%d) res %s \n",
231 *atoms
->atomname
[ai
],ai
,*atoms
->atomname
[aj
],aj
,
232 *(atoms
->resname
[atoms
->atom
[ai
].resnr
]));
233 for(j
=0; (j
<asize(dodist
)) && (blen
== NOBOND
); j
++) {
235 nra
= interaction_function
[ftype
].nratoms
;
237 for(i
=0; (i
<ilist
[ftype
].nr
) && (blen
== NOBOND
); i
+=nra
+1) {
238 type
= ilist
[ftype
].iatoms
[i
];
239 aai
= ilist
[ftype
].iatoms
[i
+1];
240 aaj
= ilist
[ftype
].iatoms
[i
+2];
242 if (((aai
== ai
) && (aaj
== aj
)) || ((aaj
== ai
) && (aai
== aj
))) {
245 blen
= sqrt(iparams
[type
].harmonic
.rA
);
248 blen
= iparams
[type
].harmonic
.rA
;
251 blen
= iparams
[type
].morse
.b0
;
254 blen
= iparams
[type
].shake
.dA
;
263 if (blen
== NOBOND
) {
265 fatal_error(0,"No bond between atoms %d and %d\n",ai
,aj
);
271 /* This should be the only conversion from nanometer to Angstrom */
274 real
lookup_angle(int ai
,int aj
,int ak
,t_ilist ilist
[],
275 t_iparams iparams
[],t_atoms
*atoms
)
277 int ft
[] = { F_ANGLES
, F_G96ANGLES
};
278 int i
,j
,type
,ff
,ftype
,aai
,aaj
,aak
,nra
;
281 /* First check the Engh & Huber database */
282 angle
= DEG2RAD
*do_specialangle(*atoms
->atomname
[ai
],*atoms
->atomname
[ak
],
283 *atoms
->resname
[atoms
->atom
[ak
].resnr
]);
284 /* Now check the topology */
285 for(ff
=0; (ff
<asize(ft
)) && (angle
== 0); ff
++) {
287 nra
= interaction_function
[ftype
].nratoms
;
289 for(i
=0; (i
<ilist
[ftype
].nr
) && (angle
== 0); i
+=nra
+1) {
290 type
= ilist
[ftype
].iatoms
[i
];
291 aai
= ilist
[ftype
].iatoms
[i
+1];
292 aaj
= ilist
[ftype
].iatoms
[i
+2];
293 aak
= ilist
[ftype
].iatoms
[i
+3];
295 if (((aai
== ai
) && (aaj
== aj
) && (aak
== ak
)) ||
296 ((aak
== ai
) && (aaj
== aj
) && (aai
== ak
))) {
297 if (ftype
== F_ANGLES
)
298 angle
= DEG2RAD
*iparams
[type
].harmonic
.rA
;
299 else if (ftype
== F_G96ANGLES
)
300 angle
= acos(iparams
[type
].harmonic
.rA
);
302 fatal_error(0,"Unknown angletype %s in %s, line %d",
303 interaction_function
[ftype
].longname
,__FILE__
,__LINE__
);
309 "Warning: no known angle between atoms %d, %d, %d. Using 109.47\n",
311 angle
= 109.47*DEG2RAD
;
316 real
angle_length(int ai
,int aj
,int ak
,real theta
,
317 t_ilist ilist
[],t_iparams iparams
[],t_atoms
*atoms
)
321 rij
= lookup_bondlength(ai
,aj
,ilist
,iparams
,TRUE
,atoms
);
322 rjk
= lookup_bondlength(aj
,ak
,ilist
,iparams
,TRUE
,atoms
);
325 fprintf(debug
,"angle_length uses %g %g and angle %g\n",rij
,rjk
,theta
);
327 return sqrt(rij
*rij
+rjk
*rjk
-2.0*rij
*rjk
*cos(DEG2RAD
*theta
));
331 static void special_bonds(t_dist *d,t_atoms *atoms,
332 char *res,int nbonds,t_bonddef bdef[])
334 int i,j,k,resnr,na,ai,aj,ndist;
337 for(i=0; (i<atoms->nr); i++) {
338 if (strcmp(*atoms->resname[atoms->atom[i].resnr],res) == 0) {
339 resnr = atoms->atom[i].resnr;
340 for(k=0; (k<nbonds); k++) {
342 for(j=i; ((j<atoms->nr) && (atoms->atom[j].resnr == resnr)); j++) {
343 if (strcmp(bdef[k].ai,*atoms->atomname[j]) == 0)
345 fatal_error(0,"Atom %s multiply defined in res %s %d",
346 bdef[k].ai,res,resnr);
349 if (strcmp(bdef[k].aj,*atoms->atomname[j]) == 0)
351 fatal_error(0,"Atom %s multiply defined in res %s %d",
352 bdef[k].aj,res,resnr);
356 if ((ai != -1) && (aj != -1)) {
357 lb=(1.0-pep_margin)*bdef[k].len;
358 ub=(1.0+pep_margin)*bdef[k].len;
359 if (((weight[ai] != 0.0) || (weight[aj] != 0.0)) &&
360 (!dist_set(d,natoms,ai,aj))) {
361 set_dist(d,natoms,ai,aj,lb,ub,len);
367 /* Optimizations ... */
369 fprintf(stderr,"There were %d special distances defined (GROMOS-override)",
375 void pdih_lengths(int ai
,int aj
,int ak
,int al
,
376 t_ilist ilist
[],t_iparams iparams
[],
377 real
*lb
,real
*ub
,t_atoms
*atoms
)
379 /* Returns the length corresponding to a cis dihedral */
380 real rij
,rjk
,rkl
,rik
;
382 real half_pi
= M_PI
*0.5;
384 rij
= lookup_bondlength(ai
,aj
,ilist
,iparams
,TRUE
,atoms
);
385 rjk
= lookup_bondlength(aj
,ak
,ilist
,iparams
,TRUE
,atoms
);
386 rkl
= lookup_bondlength(ak
,al
,ilist
,iparams
,TRUE
,atoms
);
387 th1
= lookup_angle(ai
,aj
,ak
,ilist
,iparams
,atoms
);
388 th2
= lookup_angle(aj
,ak
,al
,ilist
,iparams
,atoms
);
390 /* Compute distance from i to k using law of cosines */
391 rik
= sqrt(rij
*rij
+rjk
*rjk
-2.0*rij
*rjk
*cos(th1
));
393 /* Compute angle th3 using law of sines */
394 th3
= asin(rij
*sin(th1
)/rik
);
396 /* Compute cis length using law of cosines */
397 *lb
= sqrt(rik
*rik
+rkl
*rkl
-2.0*rik
*rkl
*cos(th2
-th3
));
399 /* Compute trans length using law of cosines */
400 *ub
= sqrt(rik
*rik
+rkl
*rkl
-2.0*rik
*rkl
*cos(th2
+th3
));
403 real
idih_lengths(int ai
,int aj
,int ak
,int al
,
404 t_ilist ilist
[],t_iparams iparams
[],t_atoms
*atoms
)
406 /* Returns the length corresponding to a cis dihedral */
407 real rij
,rjk
,rkl
,rik
;
408 real th1
,th2
,th3
,cis
;
409 real half_pi
= M_PI
*0.5;
414 if ((rij
= lookup_bondlength(ai
,aj
,ilist
,iparams
,FALSE
,atoms
)) == NOBOND
)
416 if ((rjk
= lookup_bondlength(aj
,ak
,ilist
,iparams
,FALSE
,atoms
)) == NOBOND
)
418 if ((rkl
= lookup_bondlength(ak
,al
,ilist
,iparams
,FALSE
,atoms
)) == NOBOND
)
422 fprintf(debug
,"Found an improper: %d %d %d %d\n",ai
,aj
,ak
,al
);
423 th1
= lookup_angle(ai
,aj
,ak
,ilist
,iparams
,atoms
);
424 th2
= lookup_angle(aj
,ak
,al
,ilist
,iparams
,atoms
);
426 /* Compute distance from i to k using law of cosines */
427 rik
= sqrt(rij
*rij
+rjk
*rjk
-2.0*rij
*rjk
*cos(th1
));
429 /* Compute angle th3 using law of sines */
430 th3
= asin(rij
*sin(th1
)/rik
);
432 /* Compute cis length using law of cosines */
433 return sqrt(rik
*rik
+rkl
*rkl
-2.0*rik
*rkl
*cos(th2
-th3
));