4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Copyright (c) 1991-2001, University of Groningen, The Netherlands
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * If you want to redistribute modifications, please consider that
18 * scientific software is very special. Version control is crucial -
19 * bugs must be traceable. We will be happy to consider code for
20 * inclusion in the official distribution, but derived work must not
21 * be called official GROMACS. Details are found in the README & COPYING
22 * files - if they are missing, get the official version at www.gromacs.org.
24 * To help us fund GROMACS development, we humbly ask that you cite
25 * the papers on the package - you can find them in the top README file.
27 * For more info, check our website at http://www.gromacs.org
30 * Gromacs Runs One Microsecond At Cannonball Speeds
32 static char *SRCID_correct_c
= "$Id$";
51 #define debug_gmx() do { FILE *fp=debug ? debug : (stdlog ? stdlog : stderr);\
52 fprintf(fp,"PID=%d, %s %d\n",gmx_cpu_id(),__FILE__,__LINE__); fflush(fp); } while (0)
56 #define myrand(seed) rando(seed)
58 static unsigned int IA
=16807;
59 static unsigned int IM
=2147483647;
60 static unsigned int IQ
=127773;
61 static unsigned int IR
=2836;
62 static unsigned int MASK
=123459876;
70 float myrand(int *seed
)
77 *seed
= IA
*(*seed
-k
*IQ
)-IR
*k
;
78 if (*seed
< 0) *seed
+= IM
;
86 real
mygauss(int *seed
,real lb
,real ub
)
94 return lb
+0.125*(ub
-lb
);
97 void randomize_list(int n
,int ip
[],int *seed
)
101 for(i
=0; (i
<n
); i
++) {
102 iran
= ((int) (myrand(seed
)*n
)) % n
;
109 void reset_list(int n
,int ip
[])
117 int update_list(t_dist d
[],int tag
[],int natom
,bool bViol
[],int ip
[])
122 for(i
=0; (i
<natom
); i
++) {
126 for(j
=j0
; (j
<j1
); j
++) {
128 fatal_error(0,"Tags or distances inconsistent: "
129 "i=%d, j=%d, ai=%d, aj=%d, j0=%d, j1=%d",
130 i
,j
,d
[j
].ai
,d
[j
].aj
,j0
,j1
);
136 for(j
=j0
; (j
<j1
); j
++) {
138 fatal_error(0,"Tags or distances inconsistent: "
139 "i=%d, j=%d, ai=%d, aj=%d, j0=%d, j1=%d",
140 i
,j
,d
[j
].ai
,d
[j
].aj
,j0
,j1
);
141 if (bViol
[d
[j
].aj
]) {
151 bool mirror_xx(int n1
,int n2
,int n3
,int n4
,rvec x
[],bool bViol
[],real xi
)
153 /* Check the impropers, and fix if necessary */
154 /* adapt the coordinates of atom n4 such that it is mirrorred
155 * with respect to the plane defined by n1,n2,n3 (n1 origin)
157 rvec v1
,v2
,x4old
,n
,d14
;
161 copy_rvec(x
[n4
],x4old
);
163 /* v1 and v2 span the plane */
164 rvec_sub(x
[n2
],x
[n1
],v1
);
165 rvec_sub(x
[n3
],x
[n1
],v2
);
166 rvec_sub(x
[n1
],x
[n4
],d14
);
168 /* Take the normal vector to the plane */
172 /* Check for x[n1], x[n2], x[n3] on a line, if so come back next iteration */
176 /* Find the point in which the vector parallel to n thru x[n4]
177 * intersects with the plane:
178 * by solving (x[n4]+lambda*n) . n = x[n1] . n
181 lambda
= iprod(d14
,n
)/nsq
;
183 /* Check on the improper: If it is really far off than we should not
184 * try to correct if, as this may only make it worse. The limits below
185 * indicate a range that when mirrored will become a normal improper
188 if ((xi
< -10) && (xi
> -60)) {
189 /* The fourth atom is at the wrong side of the plane, fix it. */
191 /* Mirror all four atoms around the plane parallel to 123, going thru
192 * the center of mass of the four atoms. It is easy to see that there
193 * is no center-of-mass displacement this way.
195 for(m
=0; (m
<DIM
); m
++) {
196 dn
= 0.5*lambda
*n
[m
];
203 fprintf(debug
,"improper: %d %d %d %d, xi = %g deg.\n",
204 n1
+1,n2
+1,n3
+1,n4
+1,xi
);
205 fprintf(debug
,"lambda = %g, n = (%g,%g,%g)\n",lambda
,n
[XX
],n
[YY
],n
[ZZ
]);
206 fprintf(debug
,"x4old = (%g,%g,%g) new = (%g,%g,%g)\n",
207 x4old
[XX
],x4old
[YY
],x4old
[ZZ
],x
[n4
][XX
],x
[n4
][YY
],x
[n4
][ZZ
]);
218 void compute_dihs(FILE *log
,int nq
,t_quadruple q
[],rvec x
[],real phi
[],
222 rvec r_ij
,r_kj
,r_kl
,m
,n
;
225 for(i
=0; (i
<nq
); i
++)
226 phi
[i
] = RAD2DEG
*dih_angle(box
,
227 x
[q
[i
].ai
],x
[q
[i
].aj
],x
[q
[i
].ak
],x
[q
[i
].al
],
228 r_ij
,r_kj
,r_kl
,m
,n
,&cos_phi
,&sign
);
231 int check_impropers(FILE *log
,t_correct
*c
,int natom
,rvec x
[],matrix box
)
234 int i
,nmirror
,nwrong
;
239 compute_dihs(log
,c
->nimp
,c
->imp
,x
,c
->idih
,box
);
241 for(i
=0; (i
<c
->nimp
); i
++)
244 if (nwrong
> c
->nimp
/2) {
246 fprintf(debug
,"Flipping entire molecule\n");
247 for(i
=0; (i
<natom
); i
++)
248 svmul(-1.0,x
[i
],x
[i
]);
250 for(i
=0; (i
<c
->nimp
); i
++)
251 if (mirror_xx(c
->imp
[i
].ai
,c
->imp
[i
].aj
,c
->imp
[i
].ak
,c
->imp
[i
].al
,
252 x
,c
->bViol
,c
->idih
[i
]))
254 if (debug
&& (nmirror
> 0))
255 fprintf(debug
,"mirrored %d improper dihedrals\n",nmirror
);
258 nmirror
= c
->nimp
- nmirror
;
263 int check_cis_trans(FILE *log
,t_correct
*c
,rvec x
[],matrix box
)
270 compute_dihs(log
,c
->npep
,c
->pepbond
,x
,c
->omega
,box
);
271 for(i
=0; (i
<c
->npep
); i
++) {
272 /* If one of the peptide bonds is cis, then swap H and Ca */
273 if ((c
->omega
[i
] < -90) || (c
->omega
[i
] > 90)) {
274 copy_rvec(x
[c
->pepbond
[i
].al
],temp
);
275 copy_rvec(x
[c
->pepbond
[i
].am
],x
[c
->pepbond
[i
].al
]);
276 copy_rvec(temp
,x
[c
->pepbond
[i
].am
]);
277 /* These are now violated! */
278 c
->bViol
[c
->pepbond
[i
].al
] = TRUE
;
279 c
->bViol
[c
->pepbond
[i
].am
] = TRUE
;
283 if (debug
&& (nswap
> 0))
284 fprintf(debug
,"swapped %d peptide bonds\n",nswap
);
289 bool do_1steep(int ai
, int aj
, rvec dx
,
290 real len
, real lb
, real ub
, real wi
,
291 real
*dev
, real
*maxdev
, real
*ener
, rvec fptr
[],
295 real ndev
,wj
,guess
,ddx
,delta
;
297 /* Violated bounds ? */
298 if ((len
< lb
) || (len
> ub
)) {
299 /* Update counters */
310 *ener
+= (ndev
*ndev
);
311 *maxdev
= max(*maxdev
,ndev
);
313 /* Set violation flag */
317 /* Correct non-bondeds only every N steps */
320 /* Calculate the force, that is the deviation from the nearest
321 * bound. This is the steepest descent minimizaton part.
323 delta
= (len
-guess
)/len
;
324 for(m
=0; (m
<DIM
); m
++) {
326 fptr
[ai
][m
] += wi
*ddx
;
327 fptr
[aj
][m
] -= wj
*ddx
;
335 bool do_1shake(int cons_type
,
336 int ai
, int aj
, rvec dx
,
337 real len
, real lb
, real ub
, real wi
,
338 real
*dev
, real
*maxdev
, real
*ener
, rvec xptr
[],
339 bool bViol
[], int *seed
, bool bLowerOnly
)
342 real ndev
,delta
,ddx
,wj
,guess
;
344 /* Violated bounds ? */
345 if ((len
< lb
) || ((cons_type
!= edcNONBOND
) && (len
> ub
))) {
346 /* Update counters */
347 if (cons_type
== edcNONBOND
)
356 *ener
+= (ndev
*ndev
);
357 *maxdev
= max(*maxdev
,ndev
);
359 /* Set violation flag */
364 if (cons_type
== edcBOND
)
365 guess
= mygauss(seed
,lb
,ub
);
367 guess
= lb
+ myrand(seed
)*(ub
-lb
);
369 delta
= (len
-guess
)/len
;
370 for(m
=0; (m
<DIM
); m
++) {
372 xptr
[ai
][m
] += wi
*ddx
;
373 xptr
[aj
][m
] -= wj
*ddx
;
381 int shake_coords(FILE *log
,bool bVerbose
,
382 int nstruct
,int natom
,rvec xref
[],
383 rvec x
[],int *seed
,matrix box
,t_correct
*c
,int *niter
)
385 static bool bFirst
=TRUE
;
386 static rvec
*force
[2],*xtry
[2],*xwr
;
387 int nit
,nchk
,low
,oldlow
;
388 int i
,j
,k
,l
,m
,ai
,aj
,status
,nprint
;
389 int nviol
[edcNR
],nvtot
,nswap
,nmirror
,cons_type
;
390 bool bShort
,bConverged
,bNB
,bPrint
,bLowDev
,bExplicit
,bMyNB
,bLowerOnly
;
393 real lb
,ub
,lbfac
,wi
,len
,dev
,maxdev
,len2
;
394 real step
,maxforce
=0,rstep
,step0
;
400 rvec dx
,xcm
,*xptr
,*fptr
;
403 /* Initiate local variables */
410 bExplicit
= c
->bExplicit
;
413 bLowerOnly
= c
->bLowerOnly
;
422 snew(force
[0],natom
);
423 snew(force
[1],natom
);
433 sprintf(buf
,"test%d.xtc",nstruct
);
434 status
= open_xtc(buf
,"w");
435 center_in_box(natom
,x
,box
,xwr
);
436 write_xtc(status
,natom
,0,0,box
,xwr
,1000.0);
438 for(i
=0; (i
<natom
); i
++) {
439 copy_rvec(x
[i
],xtry
[cur
][i
]);
440 copy_rvec(x
[i
],xtry
[next
][i
]);
445 if (c
->bRanlistFirst
)
446 randomize_list(nchk
,ip
,seed
);
448 for(nit
=0; ((nit
< c
->maxnit
) && !bConverged
); nit
++) {
449 /* Reset violation counters */
450 for(i
=0; (i
<natom
); i
++)
453 /* Set progress indicators */
454 nviol
[edcNONBOND
] = 0;
461 /* Nonbonded growing factor */
462 lbfac
= (c
->ngrow
== 0) ? 1.0 : (min(1.0,(real
)nit
/(real
)c
->ngrow
));
464 /* Set step dependent flags */
465 bNB
= (c
->nbcheck
!= 0) && (nit
% c
->nbcheck
) == 0;
466 bPrint
= (c
->nstprint
!= 0) && (nit
% c
->nstprint
) == 0;
467 bExplicit
= bLowDev
&& c
->bExplicit
;
469 if (c
->nstranlist
&& ((nit
% c
->nstranlist
) == 0))
470 randomize_list(nchk
,ip
,seed
);
475 for(i
=0; (i
<natom
); i
++)
481 /* Loop over distance list */
482 for(l
=0; (l
<nchk
); l
++) {
490 cons_type
= d
[k
].cons_type
;
492 if (cons_type
== edcNONBOND
) {
499 if (bMyNB
|| (cons_type
!= edcNONBOND
)) {
500 /* Compute distance */
502 for(m
=0; (m
<DIM
); m
++) {
503 dx
[m
] = xptr
[aj
][m
] - xptr
[ai
][m
];
509 bVNow
= do_1steep(ai
,aj
,dx
,len
,lb
,ub
,wi
,&dev
,&maxdev
,&ener
[next
],
512 bVNow
= do_1shake(cons_type
,ai
,aj
,
513 dx
,len
,lb
,ub
,wi
,&dev
,&maxdev
,&ener
[next
],
514 xptr
,bViol
,seed
,bLowerOnly
);
516 if (bVNow
&& c
->bDump
&& debug
) {
517 center_in_box(natom
,xptr
,box
,xwr
);
518 write_xtc(status
,natom
,nit
,(real
)l
,box
,xwr
,1000.0);
527 if (ener
[next
] < ener
[cur
]) {
530 for(i
=0; (i
<natom
); i
++)
531 for(m
=0; (m
<DIM
); m
++)
532 maxforce
= max(maxforce
,fabs(fptr
[i
][m
]));
533 /* Increase step again */
534 step
= min(step0
,2*step
);
535 rstep
= step
/maxforce
;
536 for(i
=0; (i
<natom
); i
++)
537 for(m
=0; (m
<DIM
); m
++)
538 xtry
[next
][i
][m
] = xtry
[cur
][i
][m
] + fptr
[i
][m
]*rstep
;
542 /* Decrease step size and try again */
544 rstep
= step
/maxforce
;
545 for(i
=0; (i
<natom
); i
++)
546 for(m
=0; (m
<DIM
); m
++)
547 xtry
[next
][i
][m
] = xtry
[cur
][i
][m
] + fptr
[i
][m
]*rstep
;
550 if (c
->bDump
&& bPrint
) {
551 center_in_box(natom
,xptr
,box
,xwr
);
552 write_xtc(status
,natom
,nit
,(real
)nit
+1,box
,xwr
,1000.0);
554 /* Check Impropers */
555 nmirror
= check_impropers(bVerbose
? log
: NULL
,c
,natom
,xptr
,box
);
557 /* Check peptide bonds */
558 nswap
= check_cis_trans(bVerbose
? log
: NULL
,c
,xptr
,box
);
560 nvtot
= (nviol
[edcNONBOND
] + nviol
[edcBOND
] + nviol
[edcDISRE
] +
563 if ((nprint
% 20) == 0)
564 fprintf(stderr
,"\n%5s%7s%7s%7s%7s%7s%7s%7s %10s %10s\n",
565 "nit","nchk","nimp","npep",
566 edc_names
[edcNONBOND
],edc_names
[edcBOND
],edc_names
[edcDISRE
],
568 bExplicit
? "ener A^2" : "<dev>");
569 fprintf(stderr
,"%5d%7d%7d%7d%7d%7d%7d%7d %10.4e %10.4e\n",
570 nit
,nchk
,nmirror
,nswap
,
571 nviol
[edcNONBOND
],nviol
[edcBOND
],nviol
[edcDISRE
],nvtot
,maxdev
,
572 bExplicit
? ener
[cur
] : dev
/natom
);
575 bLowDev
= (bLowDev
|| (dev
/natom
< c
->lodev
));
577 /* Update neighbour list */
580 nchk
= update_list(c
->d
,c
->tag
,natom
,bViol
,ip
);
582 bConverged
= (nchk
== 0);
586 bConverged
= (nvtot
== 0);
592 /* Copy final structure back to input array */
593 for(i
=0; (i
<natom
); i
++)
594 copy_rvec(xptr
[i
],x
[i
]);
596 fprintf(log
,"struct: %5d, box: %8.3f %8.3f %8.3f\n",
597 nstruct
,box
[XX
][XX
],box
[YY
][YY
],box
[ZZ
][ZZ
]);
598 fprintf(log
,"Converged: %3s nit: %5d <dev>: %8.4f maxdev: %8.4f\n",
599 yesno_names
[bConverged
],nit
,dev
/natom
,maxdev
);
606 int quick_check(FILE *log
,int natom
,rvec x
[],matrix box
,t_correct
*c
)
608 int i
,j
,k
,m
,ai
,aj
,nviol
;
609 real lb
,ub
,len
,len2
,dx
;
612 fprintf(log
,"Double checking final structure\n");
614 for(k
=0; (k
<c
->ndist
); k
++) {
621 /* Compute distance */
623 for(m
=0; (m
<DIM
); m
++) {
624 dx
= x
[aj
][m
] - x
[ai
][m
];
628 if ((len
< lb
) || ((ub
> 0) && (len
> ub
))) {
630 fprintf(debug
,"VIOL: ai=%4d aj=%4d lb=%8.4f len=%8.4f ub=%8.4f\n",
635 /* Check Impropers */
636 /* nmirror = check_impropers(log,c,natom,x,box);*/
638 /* Check peptide bonds */
639 /* nswap = check_cis_trans(log,c,x,box);*/