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_autocorr_c
= "$Id$";
45 #define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
46 #define MODE(x) ((mode & (x)) == (x))
50 int nrestart
,nout
,P
,nfitparm
;
51 bool bFour
,bNormalize
;
52 real tbeginfit
,tendfit
;
55 static bool bACFinit
= FALSE
;
60 void four1(fftreal data
[],int nn
,int isign
)
62 int n
,mmax
,m
,j
,istep
,i
;
63 double wtemp
,wr
,wpr
,wpi
,wi
,theta
;
70 SWAP(data
[j
],data
[i
]);
71 SWAP(data
[j
+1],data
[i
+1]);
74 while (m
>= 2 && j
> m
) {
83 theta
=6.28318530717959/(isign
*mmax
);
85 wpr
= -2.0*wtemp
*wtemp
;
89 for (m
=1;m
<mmax
;m
+=2) {
90 for (i
=m
;i
<=n
;i
+=istep
) {
92 tempr
=wr
*data
[j
]-wi
*data
[j
+1];
93 tempi
=wr
*data
[j
+1]+wi
*data
[j
];
94 data
[j
]=data
[i
]-tempr
;
95 data
[j
+1]=data
[i
+1]-tempi
;
99 wr
=(wtemp
=wr
)*wpr
-wi
*wpi
+wr
;
100 wi
=wi
*wpr
+wtemp
*wpi
+wi
;
108 void realft(fftreal data
[],int n
,int isign
)
110 int i
,i1
,i2
,i3
,i4
,n2p3
;
111 fftreal c1
=0.5,c2
,h1r
,h1i
,h2r
,h2i
;
112 double wr
,wi
,wpr
,wpi
,wtemp
,theta
;
114 theta
=3.141592653589793/(double) n
;
122 wtemp
=sin(0.5*theta
);
123 wpr
= -2.0*wtemp
*wtemp
;
128 for (i
=2;i
<=n
/2;i
++) {
129 i4
=1+(i3
=n2p3
-(i2
=1+(i1
=i
+i
-1)));
130 h1r
=c1
*(data
[i1
]+data
[i3
]);
131 h1i
=c1
*(data
[i2
]-data
[i4
]);
132 h2r
= -c2
*(data
[i2
]+data
[i4
]);
133 h2i
=c2
*(data
[i1
]-data
[i3
]);
134 data
[i1
]=h1r
+wr
*h2r
-wi
*h2i
;
135 data
[i2
]=h1i
+wr
*h2i
+wi
*h2r
;
136 data
[i3
]=h1r
-wr
*h2r
+wi
*h2i
;
137 data
[i4
] = -h1i
+wr
*h2i
+wi
*h2r
;
138 wr
=(wtemp
=wr
)*wpr
-wi
*wpi
+wr
;
139 wi
=wi
*wpr
+wtemp
*wpi
+wi
;
142 data
[1] = (h1r
=data
[1])+data
[2];
143 data
[2] = h1r
-data
[2];
145 data
[1]=c1
*((h1r
=data
[1])+data
[2]);
146 data
[2]=c1
*(h1r
-data
[2]);
151 void twofft(fftreal data1
[],fftreal data2
[],fftreal fft1
[],fftreal fft2
[],int n
)
154 fftreal rep
,rem
,aip
,aim
;
157 for (j
=1,jj
=2;j
<=n
;j
++,jj
+=2) {
164 for (j
=3;j
<=n
+1;j
+=2) {
165 rep
=0.5*(fft1
[j
]+fft1
[nn2
-j
]);
166 rem
=0.5*(fft1
[j
]-fft1
[nn2
-j
]);
167 aip
=0.5*(fft1
[j
+1]+fft1
[nn3
-j
]);
168 aim
=0.5*(fft1
[j
+1]-fft1
[nn3
-j
]);
180 enum { enNorm
, enCos
, enSin
};
182 void correl(fftreal data1
[],fftreal data2
[],int n
,fftreal ans
[])
188 twofft(data1
,data2
,fft
,ans
,n
);
190 for (i
=2;i
<=n
+2;i
+=2) {
192 ans
[i
-1] = (fft
[i
-1]*dum
+fft
[i
]*ans
[i
])/no2
;
193 ans
[i
] = (fft
[i
]*dum
-fft
[i
-1]*ans
[i
])/no2
;
200 static void low_do_four_core(int nfour
,int nframes
,real c1
[],fftreal cfour
[],
201 int nCos
,bool bPadding
)
209 for(i
=0; (i
<nframes
); i
++) {
215 for(i
=0; (i
<nframes
); i
++)
219 for(i
=0; (i
<nframes
); i
++)
223 fatal_error(0,"nCos = %d, %s %d",nCos
,__FILE__
,__LINE__
);
225 for( ; (i
<nfour
); i
++)
230 /* fprintf(stderr,"aver = %g\n",aver); */
231 for(i
=0; (i
<nframes
); i
++)
236 correl(cfour
-1,cfour
-1,nfour
,ans
-1);
239 for (i
=0; (i
<nfour
); i
++)
240 cfour
[i
] = ans
[i
]+sqr(aver
);
242 for (i
=0; (i
<nfour
); i
++)
248 static void do_ac_core(int nframes
,int nout
,
249 real corr
[],real c1
[],int nrestart
,
257 fprintf(stderr
,"WARNING: setting number of restarts to 1\n");
262 "Starting do_ac_core: nframes=%d, nout=%d, nrestart=%d,mode=%lu\n",
263 nframes
,nout
,nrestart
,mode
);
265 for(j
=0; (j
<nout
); j
++)
268 /* Loop over starting points. */
269 for(j
=0; (j
<nframes
); j
+=nrestart
) {
272 /* Loop over the correlation length for this starting point */
273 for(k
=0; (k
<nout
) && (j
+k
< nframes
); k
++) {
276 /* Switch over possible ACF types.
277 * It might be more efficient to put the loops inside the switch,
278 * but this is more clear, and save development time!
280 if (MODE(eacNormal
)) {
281 corr
[k
] += c1
[j
]*c1
[j
+k
];
283 else if (MODE(eacCos
)) {
284 /* Compute the cos (phi(t)-phi(t+dt)) */
285 corr
[k
] += cos(c1
[j
]-c1
[j
+k
]);
287 else if (MODE(eacP1
) || MODE(eacP2
) || MODE(eacP3
)) {
288 for(m
=0; (m
<DIM
); m
++) {
292 cth
=cos_angle(xj
,xk
);
294 if (cth
-1.0 > 1.0e-15) {
295 fprintf(stderr
,"j: %d, k: %d, xj:(%g,%g,%g), xk:(%g,%g,%g)\n",
296 j
,k
,xj
[XX
],xj
[YY
],xj
[ZZ
],xk
[XX
],xk
[YY
],xk
[ZZ
]);
299 corr
[k
] += LegendreP(cth
,mode
); /* 1.5*cth*cth-0.5; */
301 else if (MODE(eacRcross
)) {
302 for(m
=0; (m
<DIM
); m
++) {
308 corr
[k
] += iprod(rr
,rr
);
310 else if (MODE(eacVector
)) {
311 for(m
=0; (m
<DIM
); m
++) {
320 fatal_error(0,"\nInvalid mode (%d) in do_ac_core",mode
);
323 /* Correct for the number of points and copy results to the data array */
324 for(j
=0; (j
<nout
); j
++) {
325 n
= (nframes
-j
+(nrestart
-1))/nrestart
;
330 void normalize_acf(int nout
,real corr
[])
336 fprintf(debug
,"Before normalization\n");
337 for(j
=0; (j
<nout
); j
++)
338 fprintf(debug
,"%5d %10f\n",j
,corr
[j
]);
341 /* Normalisation makes that c[0] = 1.0 and that other points are scaled
348 for(j
=0; (j
<nout
); j
++)
352 fprintf(debug
,"After normalization\n");
353 for(j
=0; (j
<nout
); j
++)
354 fprintf(debug
,"%5d %10f\n",j
,corr
[j
]);
358 void average_acf(int n
,int nitem
,real
**c1
)
363 fprintf(stderr
,"Averaging correlation functions\n");
365 for(j
=0; (j
<n
); j
++) {
367 for(i
=0; (i
<nitem
); i
++)
373 void norm_and_scale_vectors(int nframes
,real c1
[],real scale
)
378 for(j
=0; (j
<nframes
); j
++) {
381 for(m
=0; (m
<DIM
); m
++)
386 void dump_tmp(char *s
,int n
,real c
[])
393 fprintf(fp
,"%10d %10g\n",i
,c
[i
]);
397 real
print_and_integrate(FILE *fp
,int n
,real dt
,real c
[])
402 /* Use trapezoidal rule for calculating integral */
404 for(j
=0; (j
<n
); j
++) {
407 fprintf(fp
,"%10.3f %10.5f\n",j
*dt
,c0
);
415 void do_four_core(unsigned long mode
,int nfour
,int nf2
,int nframes
,
416 real c1
[],real csum
[],real ctmp
[])
425 if (MODE(eacNormal
)) {
426 /********************************************
428 ********************************************/
429 low_do_four_core(nfour
,nf2
,c1
,csum
,enNorm
,FALSE
);
431 else if (MODE(eacCos
)) {
432 /***************************************************
434 ***************************************************/
435 /* Copy the data to temp array. Since we need it twice
436 * we can't overwrite original.
438 for(j
=0; (j
<nf2
); j
++)
441 /* Cosine term of AC function */
442 low_do_four_core(nfour
,nf2
,ctmp
,cfour
,enCos
,FALSE
);
443 for(j
=0; (j
<nf2
); j
++)
446 /* Sine term of AC function */
447 low_do_four_core(nfour
,nf2
,ctmp
,cfour
,enSin
,FALSE
);
448 for(j
=0; (j
<nf2
); j
++) {
453 else if (MODE(eacP2
)) {
454 /***************************************************
455 * Legendre polynomials
456 ***************************************************/
457 /* First normalize the vectors */
458 norm_and_scale_vectors(nframes
,c1
,1.0);
460 /* For P2 thingies we have to do six FFT based correls
461 * First for XX^2, then for YY^2, then for ZZ^2
462 * Then we have to do XY, YZ and XZ (counting these twice)
463 * After that we sum them and normalise
464 * P2(x) = (3 * cos^2 (x) - 1)/2
465 * for unit vectors u and v we compute the cosine as the inner product
466 * cos(u,v) = uX vX + uY vY + uZ vZ
470 * C(t) = | (3 cos^2(u(t'),u(t'+t)) - 1)/2 dt'
475 * P2(u(0),u(t)) = [3 * (uX(0) uX(t) +
477 * uZ(0) uZ(t))^2 - 1]/2
478 * = [3 * ((uX(0) uX(t))^2 +
481 * 2(uX(0) uY(0) uX(t) uY(t)) +
482 * 2(uX(0) uZ(0) uX(t) uZ(t)) +
483 * 2(uY(0) uZ(0) uY(t) uZ(t))) - 1]/2
485 * = [(3/2) * (<uX^2> + <uY^2> + <uZ^2> +
486 * 2<uXuY> + 2<uXuZ> + 2<uYuZ>) - 0.5]
490 /* Because of normalization the number of -0.5 to subtract
491 * depends on the number of data points!
493 for(j
=0; (j
<nf2
); j
++)
494 csum
[j
] = -0.5*(nf2
-j
);
496 /***** DIAGONAL ELEMENTS ************/
497 for(m
=0; (m
<DIM
); m
++) {
498 /* Copy the vector data in a linear array */
499 for(j
=0; (j
<nf2
); j
++)
500 ctmp
[j
] = sqr(c1
[DIM
*j
+m
]);
502 sprintf(buf
,"c1diag%d.xvg",m
);
503 dump_tmp(buf
,nf2
,ctmp
);
506 low_do_four_core(nfour
,nf2
,ctmp
,cfour
,enNorm
,FALSE
);
509 sprintf(buf
,"c1dfout%d.xvg",m
);
510 dump_tmp(buf
,nf2
,cfour
);
513 for(j
=0; (j
<nf2
); j
++)
514 csum
[j
] += fac
*(cfour
[j
]);
516 /******* OFF-DIAGONAL ELEMENTS **********/
517 for(m
=0; (m
<DIM
); m
++) {
518 /* Copy the vector data in a linear array */
520 for(j
=0; (j
<nf2
); j
++)
521 ctmp
[j
]=c1
[DIM
*j
+m
]*c1
[DIM
*j
+m1
];
524 sprintf(buf
,"c1off%d.xvg",m
);
525 dump_tmp(buf
,nf2
,ctmp
);
527 low_do_four_core(nfour
,nf2
,ctmp
,cfour
,enNorm
,FALSE
);
529 sprintf(buf
,"c1ofout%d.xvg",m
);
530 dump_tmp(buf
,nf2
,cfour
);
533 for(j
=0; (j
<nf2
); j
++) {
534 csum
[j
] += fac
*cfour
[j
];
538 else if (MODE(eacP1
) || MODE(eacVector
)) {
539 /***************************************************
541 ***************************************************/
543 /* First normalize the vectors */
544 norm_and_scale_vectors(nframes
,c1
,1.0);
547 /* For vector thingies we have to do three FFT based correls
548 * First for XX, then for YY, then for ZZ
549 * After that we sum them and normalise
551 for(j
=0; (j
<nf2
); j
++) {
554 for(m
=0; (m
<DIM
); m
++) {
555 /* Copy the vector data in a linear array */
556 for(j
=0; (j
<nf2
); j
++)
558 low_do_four_core(nfour
,nf2
,ctmp
,cfour
,enNorm
,FALSE
);
559 for(j
=0; (j
<nf2
); j
++)
564 fatal_error(0,"\nUnknown mode in do_autocorr (%d)",mode
);
567 for(j
=0; (j
<nf2
); j
++)
568 c1
[j
] = csum
[j
]/(real
)(nframes
-j
);
571 void fit_acf(int ncorr
,int nfitparm
,bool bVerbose
,
572 real tbeginfit
,real tendfit
,real dt
,real c1
[])
575 real tStart
,tail_corr
,sum
,sumtot
,*sig
;
578 fprintf(stderr
,"CORR:\n");
580 nf_int
= min(ncorr
,(int)(tendfit
/dt
));
581 sum
= print_and_integrate(debug
,ncorr
,dt
,c1
);
583 fprintf(stderr
,"CORR: Correlation time (plain integral from %6.3f to %6.3f ps) = %8.5f ps\n",
585 fprintf(stderr
,"CORR: Relaxation times are computed as fit to an exponential:\n");
587 fprintf(stderr
,"CORR: Exp[-t/tau_slope]\n");
588 else if (nfitparm
== 2)
589 fprintf(stderr
,"CORR: A Exp[-t/tau_slope]\n");
591 fatal_error(0,"nparm not set to 1 or 2, %s %d",__FILE__
,__LINE__
);
592 fprintf(stderr
,"CORR: Fit to correlation function from %6.3f ps to %6.3f ps, results in a\n",tbeginfit
,min(ncorr
*dt
,tendfit
));
595 fprintf(stderr
,"CORR:%12s%12s%12s%12s%12s\n",
596 "Integral to","Value","Tail Value","Sum (ps)","Tau (ps)");
597 for(j
=0; ((j
<5) && (tStart
< tendfit
)); j
++) {
599 fitparm
[0]=fitparm
[1]=fitparm
[2] = 1.0;
600 nf_int
= min(ncorr
,(int)((tStart
+1e-4)/dt
));
601 sum
= print_and_integrate(debug
,nf_int
,dt
,c1
);
602 tail_corr
= do_lmfit(ncorr
,c1
,sig
,dt
,tStart
,tendfit
,
603 bVerbose
,nfitparm
,NULL
,fitparm
,NULL
);
604 sumtot
= sum
+tail_corr
;
605 fprintf(stderr
,"CORR:%12.5e%12.5e%12.5e%12.5e%12.5e\n",
606 tStart
,sum
,tail_corr
,sumtot
,fitparm
[0]);
613 void low_do_autocorr(char *fn
,char *title
,
614 int nframes
,int nitem
,int nout
,real
**c1
,
615 real dt
,unsigned long mode
,int nrestart
,
616 bool bAver
,bool bFour
,bool bNormalize
,
617 bool bVerbose
,real tbeginfit
,real tendfit
,
626 /* Check flags and parameters */
627 /* nout = get_acfnout();*/
629 nout
= acf
.nout
= (nframes
+1)/2;
630 else if (nout
> nframes
)
633 if (MODE(eacCos
) && MODE(eacVector
))
634 fatal_error(0,"Incompatible options bCos && bVector (%s, %d)",
636 if ((MODE(eacP3
) || MODE(eacRcross
)) && bFour
) {
637 fprintf(stderr
,"Can't combine mode %lu with FFT, turning off FFT\n",mode
);
640 if (MODE(eacNormal
) && MODE(eacVector
))
641 fatal_error(0,"Incompatible mode bits: normal and vector (or Legendre)");
643 /* Print flags and parameters */
644 fprintf(stderr
,"Will calculate %s of %d thingies for %d frames\n",
645 title
,nitem
,nframes
);
646 fprintf(stderr
,"bAver = %s, bFour = %s bNormalize= %s\n",
647 bool_names
[bAver
],bool_names
[bFour
],bool_names
[bNormalize
]);
648 fprintf(stderr
,"mode = %lu, dt = %g, nrestart = %d\n",mode
,dt
,nrestart
);
651 c0
= log((double)nframes
)/log(2.0);
658 fprintf(debug
,"Using FFT to calculate %s, #points for FFT = %d\n",
661 /* Allocate temp arrays */
666 nfour
= 0; /* To keep the compiler happy */
671 /* Loop over items (e.g. molecules or dihedrals)
672 * In this loop the actual correlation functions are computed, but without
675 for(i
=0; (i
<nitem
); i
++) {
676 fprintf(stderr
,"\rThingie %d",i
);
679 do_four_core(mode
,nfour
,nframes
,nframes
,c1
[i
],csum
,ctmp
);
681 do_ac_core(nframes
,nout
,ctmp
,c1
[i
],nrestart
,mode
);
683 fprintf(stderr
,"\n");
687 fp
=xvgropen(fn
,title
,"Time (ps)","C(t)");
689 average_acf(nframes
,nitem
,c1
);
692 normalize_acf(nout
,c1
[0]);
694 if (tbeginfit
< tendfit
) {
695 fit_acf(nout
,nfitparm
,bVerbose
,tbeginfit
,tendfit
,dt
,c1
[0]);
696 (void)print_and_integrate(fp
,nout
,dt
,c1
[0]);
698 sum
= print_and_integrate(fp
,nout
,dt
,c1
[0]);
699 fprintf(stderr
,"Correlation time (integral over corrfn): %g (ps)\n",sum
);
703 /* Not averaging. Normalize individual ACFs */
704 for(i
=0; (i
<nitem
); i
++) {
706 normalize_acf(nout
,c1
[i
]);
707 if (tbeginfit
< tendfit
) {
708 fit_acf(nout
,nfitparm
,bVerbose
,tbeginfit
,tendfit
,dt
,c1
[i
]);
709 (void)print_and_integrate(fp
,nout
,dt
,c1
[0]);
711 sum
= print_and_integrate(fp
,nout
,dt
,c1
[i
]);
712 fprintf(stderr
,"CORRelation time (integral over corrfn %d): %g (ps)\n",
720 static char *Leg
[] = { NULL
, "0", "1", "2", "3", NULL
};
721 static char *Nparm
[] = { NULL
, "1", "2", NULL
};
723 t_pargs
*add_acf_pargs(int *npargs
,t_pargs
*pa
)
726 { "-acflen", FALSE
, etINT
, {&acf
.nout
},
727 "Length of the ACF, default is half the number of frames" },
728 { "-normalize",FALSE
, etBOOL
, {&acf
.bNormalize
},
730 { "-fft", FALSE
, etBOOL
, {&acf
.bFour
},
731 "HIDDENUse fast fourier transform for correlation function" },
732 { "-nrestart", FALSE
, etINT
, {&acf
.nrestart
},
733 "HIDDENNumber of frames between time origins for ACF when no FFT is used" },
734 { "-P", FALSE
, etENUM
, {Leg
},
735 "Order of Legendre polynomial for ACF (0 indicates none)" },
736 { "-nparm", FALSE
, etENUM
, {Nparm
},
737 "Number of parameters in exponential fit" },
738 { "-beginfit", FALSE
, etREAL
, {&acf
.tbeginfit
},
739 "Time where to begin the exponential fit of the correlation function" },
740 { "-endfit", FALSE
, etREAL
, {&acf
.tendfit
},
741 "Time where to end the exponential fit of the correlation function" },
743 #define NPA asize(acfpa)
747 snew(ppa
,*npargs
+NPA
);
748 for(i
=0; (i
<*npargs
); i
++)
750 for(i
=0; (i
<NPA
); i
++)
751 ppa
[*npargs
+i
] = acfpa
[i
];
760 acf
.bNormalize
= TRUE
;
769 void do_autocorr(char *fn
,char *title
,int nframes
,int nitem
,real
**c1
,
770 real dt
,unsigned long mode
,bool bAver
)
773 fprintf(stderr
,"ACF data structures have not been initialised. Call add_acf_pargs\n");
776 /* Handle enumerated types */
777 sscanf(Leg
[0],"%d",&acf
.P
);
778 sscanf(Nparm
[0],"%d",&acf
.nfitparm
);
794 low_do_autocorr(fn
,title
,nframes
,nitem
,acf
.nout
,c1
,dt
,mode
,
795 acf
.nrestart
,bAver
,acf
.bFour
,acf
.bNormalize
,
796 bDebugMode(),acf
.tbeginfit
,acf
.tendfit
,
800 int get_acfnout(void)
803 fatal_error(0,"ACF data not initialized yet");