4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
34 * Green Red Orange Magenta Azure Cyan Skyblue
57 static bondlist
*lst
=NULL
;
59 static void newresidue(char *residue
)
64 p
->residue
= strdup(residue
);
72 fprintf(debug
,"initialised element for residue %s\n",residue
);
75 void read_O_dist(void)
78 static char *fn
= "refi_aa.dat";
80 char buf
[BLEN
+1],buf_ai
[9],buf_aj
[9],junk1
[15],junk2
[15];
86 fprintf(stderr
,"Going to read %s\n",fn
);
87 fprintf(stderr
,"Take note that the angle O C N+ will not be read from the");
88 fprintf(stderr
," correct residue\nThis is not a problem in the current");
89 fprintf(stderr
,"(980927) param-file while \nthis angle is const. 123.000\n");
90 while (fgets2(buf
,BLEN
,fp
) != NULL
) {
98 sscanf(buf
,"%s%s",buf_ai
,buf_aj
);
99 if (strcmp(buf_ai
,"residue") == 0 ) {
101 /* O only uses HIS, Gromos has HISB... */
102 if (strcmp(buf_aj
,"HIS") == 0) strcpy(buf_aj
,"HISB");
107 if ( buf
[5] == 'd' ) {
108 sscanf(buf
,"%*s%s%s%lf",buf_ai
,buf_aj
,&dist
);
109 /*fprintf(stderr,"1: %s %s %g\n",buf_ai,buf_aj,dist);*/
110 if (strcmp(buf_ai
,"C-") == 0) strcpy(buf_ai
,"C");
111 if (strcmp(buf_ai
,"CA-") == 0) strcpy(buf_ai
,"CA");
112 if (strcmp(buf_ai
,"N+") == 0) strcpy(buf_ai
,"N");
113 if (strcmp(buf_aj
,"C-") == 0) strcpy(buf_aj
,"C");
114 if (strcmp(buf_aj
,"CA-") == 0) strcpy(buf_aj
,"CA");
115 if (strcmp(buf_aj
,"N+") == 0) strcpy(buf_aj
,"N");
116 /*fprintf(stderr,"2: %s %s %g\n",buf_ai,buf_aj,dist);*/
118 lst
->atombond
= srenew(lst
->atombond
,lst
->natombond
);
119 lst
->atombond
[lst
->natombond
-1].ai
= strdup(buf_ai
);
120 lst
->atombond
[lst
->natombond
-1].aj
= strdup(buf_aj
);
121 lst
->atombond
[lst
->natombond
-1].dist
= (dist
/10.0);
123 if ( buf
[5] == 'a' ) {
124 sscanf(buf
,"%*s%s%*s%s%lf",buf_ai
,buf_aj
,&dist
);
125 /*fprintf(stderr,"1: %s %s %g\n",buf_ai,buf_aj,dist);*/
126 if (strcmp(buf_ai
,"C-") == 0) strcpy(buf_ai
,"C");
127 if (strcmp(buf_ai
,"CA-") == 0) strcpy(buf_ai
,"CA");
128 if (strcmp(buf_ai
,"N+") == 0) strcpy(buf_ai
,"N");
129 if (strcmp(buf_aj
,"C-") == 0) strcpy(buf_aj
,"C");
130 if (strcmp(buf_aj
,"CA-") == 0) strcpy(buf_aj
,"CA");
131 if (strcmp(buf_aj
,"N+") == 0) strcpy(buf_aj
,"N");
132 /*fprintf(stderr,"2: %s %s %g\n",buf_ai,buf_aj,dist);*/
134 lst
->atomangle
= srenew(lst
->atomangle
,lst
->natomangle
);
135 lst
->atomangle
[lst
->natomangle
-1].ai
= strdup(buf_ai
);
136 lst
->atomangle
[lst
->natomangle
-1].aj
= strdup(buf_aj
);
137 lst
->atomangle
[lst
->natomangle
-1].angle
= dist
;
141 fprintf(stderr
,"Ooops! Unexpected first character in line:\n%s",buf
);
147 fprintf(stderr
,"Read distances for %d residues from file %s \n",nres
,fn
);
150 static real
do_specialbond(char *name1
,char *name2
,char *res
)
156 fprintf(debug
,"Looking for dist between %s %s in res. %s\n",
159 for ( p
= lst
; p
!= NULL
; p
= p
->next
)
160 if (strcmp(res
,p
->residue
) == 0)
163 /* Here either p == NULL or found */
164 for (i
=0; p
!= NULL
&& (i
<p
->natombond
) ; i
++) {
165 if (((strcmp(name1
,p
->atombond
[i
].ai
) == 0) &&
166 (strcmp(name2
,p
->atombond
[i
].aj
) == 0)) ||
167 ((strcmp(name1
,p
->atombond
[i
].aj
) == 0) &&
168 (strcmp(name2
,p
->atombond
[i
].ai
) == 0))) {
170 fprintf(debug
,"Found dist. %s %s %s",name1
,name2
,res
);
171 fprintf(debug
," %g\n",p
->atombond
[i
].dist
);
173 return p
->atombond
[i
].dist
;
177 fprintf(debug
,"Didn't find dist. %s %s %s\n",name1
,name2
,res
);
182 static real
do_specialangle(char *name1
,char *name2
,char *res
)
189 fprintf(debug
,"Looking for angle between %s %s in res. %s\n",
192 for ( p
= lst
; p
!= NULL
; p
= p
->next
)
193 if (strcmp(res
,p
->residue
) == 0)
196 /* Here either p == NULL or found */
197 for (i
=0; p
!= NULL
&& (i
<p
->natomangle
) ; i
++) {
198 if (((strcmp(name1
,p
->atomangle
[i
].ai
) == 0) &&
199 (strcmp(name2
,p
->atomangle
[i
].aj
) == 0)) ||
200 ((strcmp(name1
,p
->atomangle
[i
].aj
) == 0) &&
201 (strcmp(name2
,p
->atomangle
[i
].ai
) == 0))) {
203 fprintf(debug
,"Found angle. %s %s %s",name1
,name2
,res
);
204 fprintf(debug
," %g\n",p
->atomangle
[i
].angle
);
206 return p
->atomangle
[i
].angle
;
210 fprintf(debug
,"Didn't find angle %s %s %s\n",name1
,name2
,res
);
215 real
lookup_bondlength_(int ai
,int aj
,t_ilist ilist
[],
216 t_iparams iparams
[],bool bFail
,t_atoms
*atoms
,
219 int dodist
[] = { F_BONDS
, F_MORSE
, F_SHAKE
, F_G96BONDS
};
220 int i
,j
,type
,ftype
,aai
,aaj
,nra
;
225 fprintf(debug
,"call do_spec with %s (%d) %s (%d) res %s \n",
226 *atoms
->atomname
[ai
],ai
,*atoms
->atomname
[aj
],aj
,
227 *(atoms
->resname
[atoms
->atom
[ai
].resnr
]));
229 spclen
= do_specialbond(*(atoms
->atomname
[ai
]),*(atoms
->atomname
[aj
]),
230 *(atoms
->resname
[atoms
->atom
[aj
].resnr
]));
232 /* Comment; if you're using distances from e.g. O, it is non-trivial
233 which residuename (ai or aj) you call do_special with, in order
234 to get the peptide bonds correct. */
237 fprintf(debug
,"%s %d %d %g\n",*atoms
->resname
[atoms
->atom
[ai
].resnr
],
243 fprintf(debug
,"No spclen found for %s (%d) %s (%d) res %s \n",
244 *atoms
->atomname
[ai
],ai
,*atoms
->atomname
[aj
],aj
,
245 *(atoms
->resname
[atoms
->atom
[ai
].resnr
]));
246 for(j
=0; (j
<asize(dodist
)) && (blen
== NOBOND
); j
++) {
248 nra
= interaction_function
[ftype
].nratoms
;
250 for(i
=0; (i
<ilist
[ftype
].nr
) && (blen
== NOBOND
); i
+=nra
+1) {
251 type
= ilist
[ftype
].iatoms
[i
];
252 aai
= ilist
[ftype
].iatoms
[i
+1];
253 aaj
= ilist
[ftype
].iatoms
[i
+2];
255 if (((aai
== ai
) && (aaj
== aj
)) || ((aaj
== ai
) && (aai
== aj
))) {
258 blen
= sqrt(iparams
[type
].harmonic
.rA
);
261 blen
= iparams
[type
].harmonic
.rA
;
264 blen
= iparams
[type
].morse
.b0
;
267 blen
= iparams
[type
].shake
.dA
;
276 if (blen
== NOBOND
) {
278 fatal_error(0,"No bond between atoms %d and %d (called from %s line %d)\n",
285 /* This should be the only conversion from nanometer to Angstrom */
288 real
lookup_angle_(int ai
,int aj
,int ak
,t_ilist ilist
[],
289 t_iparams iparams
[],t_atoms
*atoms
,
292 int ft
[] = { F_ANGLES
, F_G96ANGLES
};
293 int i
,j
,type
,ff
,ftype
,aai
,aaj
,aak
,nra
;
296 /* First check the Engh & Huber database */
297 angle
= DEG2RAD
*do_specialangle(*atoms
->atomname
[ai
],*atoms
->atomname
[ak
],
298 *atoms
->resname
[atoms
->atom
[ak
].resnr
]);
299 /* Now check the topology */
300 for(ff
=0; (ff
<asize(ft
)) && (angle
== 0); ff
++) {
302 nra
= interaction_function
[ftype
].nratoms
;
304 for(i
=0; (i
<ilist
[ftype
].nr
) && (angle
== 0); i
+=nra
+1) {
305 type
= ilist
[ftype
].iatoms
[i
];
306 aai
= ilist
[ftype
].iatoms
[i
+1];
307 aaj
= ilist
[ftype
].iatoms
[i
+2];
308 aak
= ilist
[ftype
].iatoms
[i
+3];
310 if (((aai
== ai
) && (aaj
== aj
) && (aak
== ak
)) ||
311 ((aak
== ai
) && (aaj
== aj
) && (aai
== ak
))) {
312 if (ftype
== F_ANGLES
)
313 angle
= DEG2RAD
*iparams
[type
].harmonic
.rA
;
314 else if (ftype
== F_G96ANGLES
)
315 angle
= acos(iparams
[type
].harmonic
.rA
);
317 fatal_error(0,"Unknown angletype %s in %s, line %d",
318 interaction_function
[ftype
].longname
,__FILE__
,__LINE__
);
324 "Warning: no known angle between atoms %d, %d, %d. Using 109.47\n",
326 angle
= 109.47*DEG2RAD
;
331 real
angle_length_(int ai
,int aj
,int ak
,real theta
,
332 t_ilist ilist
[],t_iparams iparams
[],t_atoms
*atoms
,
337 rij
= lookup_bondlength_(ai
,aj
,ilist
,iparams
,TRUE
,atoms
,file
,line
);
338 rjk
= lookup_bondlength_(aj
,ak
,ilist
,iparams
,TRUE
,atoms
,file
,line
);
341 fprintf(debug
,"angle_length uses %g %g and angle %g\n",rij
,rjk
,theta
);
343 return sqrt(rij
*rij
+rjk
*rjk
-2.0*rij
*rjk
*cos(DEG2RAD
*theta
));
347 static void special_bonds(t_dist *d,t_atoms *atoms,
348 char *res,int nbonds,t_bonddef bdef[])
350 int i,j,k,resnr,na,ai,aj,ndist;
353 for(i=0; (i<atoms->nr); i++) {
354 if (strcmp(*atoms->resname[atoms->atom[i].resnr],res) == 0) {
355 resnr = atoms->atom[i].resnr;
356 for(k=0; (k<nbonds); k++) {
358 for(j=i; ((j<atoms->nr) && (atoms->atom[j].resnr == resnr)); j++) {
359 if (strcmp(bdef[k].ai,*atoms->atomname[j]) == 0)
361 fatal_error(0,"Atom %s multiply defined in res %s %d",
362 bdef[k].ai,res,resnr);
365 if (strcmp(bdef[k].aj,*atoms->atomname[j]) == 0)
367 fatal_error(0,"Atom %s multiply defined in res %s %d",
368 bdef[k].aj,res,resnr);
372 if ((ai != -1) && (aj != -1)) {
373 lb=(1.0-pep_margin)*bdef[k].len;
374 ub=(1.0+pep_margin)*bdef[k].len;
375 if (((weight[ai] != 0.0) || (weight[aj] != 0.0)) &&
376 (!dist_set(d,natoms,ai,aj))) {
377 set_dist(d,natoms,ai,aj,lb,ub,len);
383 /* Optimizations ... */
385 fprintf(stderr,"There were %d special distances defined (GROMOS-override)",
391 void pdih_lengths_(int ai
,int aj
,int ak
,int al
,
392 t_ilist ilist
[],t_iparams iparams
[],
393 real
*lb
,real
*ub
,t_atoms
*atoms
,char *file
,int line
)
395 /* Returns the length corresponding to a cis dihedral */
396 real rij
,rjk
,rkl
,rik
;
398 real half_pi
= M_PI
*0.5;
400 rij
= lookup_bondlength_(ai
,aj
,ilist
,iparams
,TRUE
,atoms
,file
,line
);
401 rjk
= lookup_bondlength_(aj
,ak
,ilist
,iparams
,TRUE
,atoms
,file
,line
);
402 rkl
= lookup_bondlength_(ak
,al
,ilist
,iparams
,TRUE
,atoms
,file
,line
);
403 th1
= lookup_angle_(ai
,aj
,ak
,ilist
,iparams
,atoms
,file
,line
);
404 th2
= lookup_angle_(aj
,ak
,al
,ilist
,iparams
,atoms
,file
,line
);
406 /* Compute distance from i to k using law of cosines */
407 rik
= sqrt(rij
*rij
+rjk
*rjk
-2.0*rij
*rjk
*cos(th1
));
409 /* Compute angle th3 using law of sines */
410 th3
= asin(rij
*sin(th1
)/rik
);
412 /* Compute cis length using law of cosines */
413 *lb
= sqrt(rik
*rik
+rkl
*rkl
-2.0*rik
*rkl
*cos(th2
-th3
));
415 /* Compute trans length using law of cosines */
416 *ub
= sqrt(rik
*rik
+rkl
*rkl
-2.0*rik
*rkl
*cos(th2
+th3
));
419 real
idih_lengths(int ai
,int aj
,int ak
,int al
,
420 t_ilist ilist
[],t_iparams iparams
[],t_atoms
*atoms
)
422 /* Returns the length corresponding to a cis dihedral */
423 real rij
,rjk
,rkl
,rik
;
424 real th1
,th2
,th3
,cis
;
425 real half_pi
= M_PI
*0.5;
430 if ((rij
= lookup_bondlength(ai
,aj
,ilist
,iparams
,FALSE
,atoms
)) == NOBOND
)
432 if ((rjk
= lookup_bondlength(aj
,ak
,ilist
,iparams
,FALSE
,atoms
)) == NOBOND
)
434 if ((rkl
= lookup_bondlength(ak
,al
,ilist
,iparams
,FALSE
,atoms
)) == NOBOND
)
438 fprintf(debug
,"Found an improper: %d %d %d %d\n",ai
,aj
,ak
,al
);
439 th1
= lookup_angle(ai
,aj
,ak
,ilist
,iparams
,atoms
);
440 th2
= lookup_angle(aj
,ak
,al
,ilist
,iparams
,atoms
);
442 /* Compute distance from i to k using law of cosines */
443 rik
= sqrt(rij
*rij
+rjk
*rjk
-2.0*rij
*rjk
*cos(th1
));
445 /* Compute angle th3 using law of sines */
446 th3
= asin(rij
*sin(th1
)/rik
);
448 /* Compute cis length using law of cosines */
449 return sqrt(rik
*rik
+rkl
*rkl
-2.0*rik
*rkl
*cos(th2
-th3
));