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
53 #include "gmxcomplex.h"
56 /* Determines at which point in the array the fit should start */
57 int calc_nbegin(int nx
,real x
[],real tbegin
)
62 /* Assume input x is sorted */
63 for(nbegin
=0; (nbegin
< nx
) && (x
[nbegin
] <= tbegin
); nbegin
++)
65 if ((nbegin
== nx
) || (nbegin
== 0))
66 fatal_error(0,"Begin time %f not in x-domain [%f through %f]\n",
69 /* Take the one closest to tbegin */
70 if (fabs(x
[nbegin
]-tbegin
) > fabs(x
[nbegin
-1]-tbegin
))
73 printf("nbegin = %d, x[nbegin] = %g, tbegin = %g\n",
74 nbegin
,x
[nbegin
],tbegin
);
79 real
numerical_deriv(int nx
,real x
[],real y
[],real fity
[],real combined
[],real dy
[],
80 real tendInt
,int nsmooth
)
84 real fac
,fx
,fy
,integralSmth
;
86 nbegin
= calc_nbegin(nx
,x
,tendInt
);
88 for(i
=0; (i
<nbegin
); i
++)
90 fac
= y
[nbegin
]/fity
[nbegin
];
91 printf("scaling fitted curve by %g\n",fac
);
92 for(i
=nbegin
; (i
<nx
); i
++)
93 combined
[i
]=fity
[i
]*fac
;
97 i1
= min(nx
-1,nbegin
+nsmooth
);
98 printf("Making smooth transition from %d thru %d\n",i0
,i1
);
101 for(i
=i0
; (i
<=i1
); i
++) {
102 fx
= (i1
-i
)/(real
)(i1
-i0
);
103 fy
= (i
-i0
)/(real
)(i1
-i0
);
105 fprintf(debug
,"x: %g factors for smoothing: %10g %10g\n",x
[i
],fx
,fy
);
106 combined
[i
] = fx
*y
[i
] + fy
*fity
[i
];
108 for(i
=i1
+1; (i
<nx
); i
++)
112 tmpfp
= ffopen("integral_smth.xvg","w");
113 integralSmth
=print_and_integrate(tmpfp
,nx
,x
[1]-x
[0],combined
,NULL
,1);
114 printf("SMOOTH integral = %10.5e\n",integralSmth
);
116 dy
[0] = (combined
[1]-combined
[0])/(x
[1]-x
[0]);
117 for(i
=1; (i
<nx
-1); i
++) {
118 dy
[i
] = (combined
[i
+1]-combined
[i
-1])/(x
[i
+1]-x
[i
-1]);
120 dy
[nx
-1] = (combined
[nx
-1]-combined
[nx
-2])/(x
[nx
-1]-x
[nx
-2]);
122 for(i
=0; (i
<nx
); i
++)
128 void do_four(char *fn
,char *cn
,int nx
,real x
[],real dy
[],real eps0
,real epsRF
)
131 t_complex
*tmp
,gw
,hw
,kw
;
133 real fac
,nu
,dt
,*ptr
,maxeps
,numax
;
136 /*while ((dy[nx-1] == 0.0) && (nx > 0))
139 fatal_error(0,"Empty dataset in %s, line %d!",__FILE__
,__LINE__
);
146 printf("Doing FFT of %d points\n",nnx
);
147 for(i
=0; (i
<nx
); i
++)
154 fac
= (eps0
-1)/tmp
[0].re
;
156 fac
=((eps0
-1)/(2*epsRF
+eps0
))/tmp
[0].re
;
157 fp
=xvgropen(fn
,"Epsilon(\\8w\\4)","Freq. (GHz)","eps");
158 cp
=xvgropen(cn
,"Cole-Cole plot","Eps'","Eps''");
161 for(i
=0; (i
<nxsav
); i
++) {
163 kw
.re
= 1+fac
*tmp
[i
].re
;
164 kw
.im
= 1+fac
*tmp
[i
].im
;
167 gw
= rcmul(fac
,tmp
[i
]);
168 hw
= rcmul(2*epsRF
,gw
);
176 nu
= (i
+1)*1000.0/(nnx
*dt
);
177 if (kw
.im
> maxeps
) {
182 fprintf(fp
,"%10.5e %10.5e %10.5e\n",nu
,kw
.re
,kw
.im
);
183 fprintf(cp
,"%10.5e %10.5e\n",kw
.re
,kw
.im
);
185 printf("MAXEPS = %10.5e at frequency %10.5e GHz (tauD = %8.1f ps)\n",
186 maxeps
,numax
,1000/(2*M_PI
*numax
));
192 int gmx_dielectric(int argc
,char *argv
[])
194 static char *desc
[] = {
195 "dielectric calculates frequency dependent dielectric constants",
196 "from the autocorrelation function of the total dipole moment in",
197 "your simulation. This ACF can be generated by g_dipoles.",
198 "For an estimate of the error you can run g_statistics on the",
199 "ACF, and use the output thus generated for this program.",
200 "The functional forms of the available functions are:[PAR]",
201 "One parmeter : y = Exp[-a1 x]",
202 "Two parmeters : y = a2 Exp[-a1 x]",
203 "Three parmeter: y = a2 Exp[-a1 x] + (1 - a2) Exp[-a3 x]",
204 "Startvalues for the fit procedure can be given on the commandline.",
205 "It is also possible to fix parameters at their start value, use -fix",
206 "with the number of the parameter you want to fix.",
208 "Three output files are generated, the first contains the ACF,",
209 "an exponential fit to it with 1, 2 or 3 parameters, and the",
210 "numerical derivative of the combination data/fit.",
211 "The second file contains the real and imaginary parts of the",
212 "frequency-dependent dielectric constant, the last gives a plot",
213 "known as the Cole-Cole plot, in which the imaginary",
214 "component is plotted as a function of the real component.",
215 "For a pure exponential relaxation (Debye relaxation) the latter",
216 "plot should be one half of a circle"
219 { efXVG
, "-f", "Mtot", ffREAD
},
220 { efXVG
, "-d", "deriv", ffWRITE
},
221 { efXVG
, "-o", "epsw", ffWRITE
},
222 { efXVG
, "-c", "cole", ffWRITE
}
224 #define NFILE asize(fnm)
225 int i
,j
,nx
,ny
,nxtail
,eFitFn
,nfitparm
;
226 real
**y
,dt
,integral
,fitintegral
,*fitparms
,fac
,rffac
;
227 char *legend
[] = { "Correlation", "Std. Dev.", "Fit", "Combined", "Derivative" };
228 static int fix
=0,bFour
= 0,bX
= 1,nsmooth
=3;
229 static real tendInt
=5.0,tbegin
=5.0,tend
=500.0;
230 static real A
=0.5,tau1
=10.0,tau2
=1.0,eps0
=80,epsRF
=78.5,tail
=500.0;
233 { "-fft", FALSE
, etBOOL
, {&bFour
},
234 "use fast fourier transform for correlation function" },
235 { "-x1", FALSE
, etBOOL
, {&bX
},
236 "use first column as X axis rather than first data set" },
237 { "-eint", FALSE
, etREAL
, {&tendInt
},
238 "Time were to end the integration of the data and start to use the fit"},
239 { "-bfit", FALSE
, etREAL
, {&tbegin
},
240 "Begin time of fit" },
241 { "-efit", FALSE
, etREAL
, {&tend
},
243 { "-tail", FALSE
, etREAL
, {&tail
},
244 "Length of function including data and tail from fit" },
245 { "-A", FALSE
, etREAL
, {&A
},
246 "Start value for fit parameter A" },
247 { "-tau1", FALSE
, etREAL
, {&tau1
},
248 "Start value for fit parameter tau1" },
249 { "-tau2", FALSE
, etREAL
, {&tau2
},
250 "Start value for fit parameter tau2" },
251 { "-eps0", FALSE
, etREAL
, {&eps0
},
252 "Epsilon 0 of your liquid" },
253 { "-epsRF", FALSE
, etREAL
, {&epsRF
},
254 "Epsilon of the reaction field used in your simulation. A value of 0 means infinity." },
255 { "-fix", FALSE
, etINT
, {&fix
},
256 "Fix parameters at their start values, A (2), tau1 (1), or tau2 (4)" },
257 { "-ffn", FALSE
, etENUM
, {s_ffn
},
259 { "-nsmooth", FALSE
, etINT
, {&nsmooth
},
260 "Number of points for smoothing" }
263 CopyRight(stderr
,argv
[0]);
264 parse_common_args(&argc
,argv
,PCA_CAN_TIME
| PCA_CAN_VIEW
| PCA_BE_NICE
,
265 NFILE
,fnm
,asize(pa
),pa
,asize(desc
),desc
,0,NULL
);
266 please_cite(stdout
,"Spoel98a");
268 nx
= read_xvg(opt2fn("-f",NFILE
,fnm
),&y
,&ny
);
269 dt
= y
[0][1]-y
[0][0];
270 nxtail
= min(tail
/dt
,nx
);
272 printf("Read data set containing %d colums and %d rows\n",ny
,nx
);
273 printf("Assuming (from data) that timestep is %g, nxtail = %d\n",
276 for(i
=0; (i
<ny
); i
++)
278 for(i
=nx
; (i
<nxtail
); i
++) {
279 y
[0][i
] = dt
*i
+y
[0][0];
280 for(j
=1; (j
<ny
); j
++)
286 /* We have read a file WITHOUT standard deviations, so we make our own... */
288 printf("Creating standard deviation numbers ...\n");
293 for(i
=0; (i
<nx
); i
++)
297 eFitFn
= sffn2effn(s_ffn
);
298 nfitparm
= nfp_ffn
[eFitFn
];
312 integral
= print_and_integrate(NULL
,calc_nbegin(nx
,y
[0],tbegin
),
314 integral
+= do_lmfit(nx
,y
[1],y
[2],dt
,y
[0],tbegin
,tend
,
315 TRUE
,eFitFn
,fitparms
,fix
);
317 y
[3][i
] = fit_function(eFitFn
,fitparms
,y
[0][i
]);
320 /* This means infinity! */
325 lambda
= (eps0
- 1.0)/(2*epsRF
- 1.0);
326 rffac
= (2*epsRF
+eps0
)/(2*epsRF
+1);
328 printf("DATA INTEGRAL: %5.1f, tauD(old) = %5.1f ps, "
329 "tau_slope = %5.1f, tau_slope,D = %5.1f ps\n",
330 integral
,integral
*rffac
,fitparms
[0],fitparms
[0]*rffac
);
332 printf("tau_D from tau1 = %8.3g , eps(Infty) = %8.3f\n",
333 fitparms
[0]*(1 + fitparms
[1]*lambda
),
334 1 + ((1 - fitparms
[1])*(eps0
- 1))/(1 + fitparms
[1]*lambda
));
336 fitintegral
=numerical_deriv(nx
,y
[0],y
[1],y
[3],y
[4],y
[5],tendInt
,nsmooth
);
337 printf("FIT INTEGRAL (tau_M): %5.1f, tau_D = %5.1f\n",
338 fitintegral
,fitintegral
*rffac
);
340 /* Now we have the negative gradient of <Phi(0) Phi(t)> */
341 write_xvg(opt2fn("-d",NFILE
,fnm
),"Data",nx
-1,6,y
,legend
);
343 /* Do FFT and analysis */
344 do_four(opt2fn("-o",NFILE
,fnm
),opt2fn("-c",NFILE
,fnm
),
345 nx
-1,y
[0],y
[5],eps0
,epsRF
);
347 do_view(opt2fn("-o",NFILE
,fnm
),"-nxy");
348 do_view(opt2fn("-c",NFILE
,fnm
),NULL
);
349 do_view(opt2fn("-d",NFILE
,fnm
),"-nxy");