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_expfit_c
= "$Id$";
43 extern void mrqmin(real x
[],real y
[],real sig
[],int ndata
,real a
[],
44 int ma
,int lista
[],int mfit
,real
**covar
,real
**alpha
,
46 void (*funcs
)(real x
,real a
[],real
*y
,real dyda
[]),
49 extern void mrqmin_new(real x
[],real y
[],real sig
[],int ndata
,real a
[],
50 int ia
[],int ma
,real
**covar
,real
**alpha
,real
*chisq
,
51 void (*funcs
)(real
, real
[], real
*, real
[]),
54 static real
myexp(real x
,real A
,real tau
)
56 if ((A
== 0) || (tau
== 0))
61 static void exp_one_parm(real x
,real a
[],real
*y
,real dyda
[])
73 dyda
[1] = x
*e1
/(a
[1]*a
[1]);
76 static void exp_two_parm(real x
,real a
[],real
*y
,real dyda
[])
88 dyda
[1] = x
*a
[2]*e1
/(a
[1]*a
[1]);
92 static void exp_3_parm(real x
,real a
[],real
*y
,real dyda
[])
96 * y = a2 exp(-x/a1) + (1-a2) exp(-x/a3)
104 *y
= a
[2]*e1
+ (1-a
[2])*e2
;
105 dyda
[1] = x
*a
[2]*e1
/(a
[1]*a
[1]);
107 dyda
[3] = x
*(1-a
[2])*e2
/(a
[3]*a
[3]);
108 /* fprintf(stderr,"exp3: x=%10.3e *y=%10.3e dyda=%10.3e %10.3e %10.3e\n",
109 x,*y,dyda[1],dyda[2],dyda[3]); */
112 /* lmfit_exp supports up to 3 parameter fitting of exponential functions */
113 static void lmfit_exp(int nframes
,real x
[],real y
[],real dy
[],real ftol
,
114 real parm
[],real dparm
[],bool bVerbose
,int nfitparm
,
117 typedef void (*myfitfn
)(real x
,real a
[],real
*y
,real dyda
[]);
118 myfitfn fitfn
[3] = { exp_one_parm
, exp_two_parm
, exp_3_parm
};
119 real chisq
,ochisq
,alamda
;
120 real
*a
,**covar
,**alpha
;
122 int i
,j
,ma
,mfit
,*lista
,*ia
;
124 if ((nfitparm
< 1) || (nfitparm
> 3))
125 fatal_error(0,"nfitparm = %d, should be in 1..3 (%s,%d)",
126 nfitparm
,__FILE__
,__LINE__
);
128 ma
=mfit
=nfitparm
; /* number of parameters to fit */
134 for(i
=1; (i
<ma
+1); i
++) {
141 fprintf(stderr
,"Will keep %s fixed during fit procedure\n",fix
);
142 if (strcmp(fix
,"tau1") == 0)
144 else if (strcmp(fix
,"A") == 0)
146 else if (strcmp(fix
,"tau2") == 0)
149 fprintf(stderr
,"%d parameter fit\n",mfit
);
152 alamda
= -1; /* Starting value */
154 a
[1] = parm
[0]; /* tau1 */
156 a
[2] = parm
[1]; /* AA */
158 a
[3] = parm
[2]; /* tau2 */
162 fprintf(stderr
,"%4s %10s %10s %10s %10s %10s\n",
163 "Step","chi^2","Lambda","A1","A2","A3");
166 /* mrqmin(x-1,y-1,dy-1,nframes,a,ma,lista,mfit,covar,alpha,
167 * &chisq,fitfn[mfit-1],&alamda);
169 mrqmin_new(x
-1,y
-1,dy
-1,nframes
,a
,ia
,ma
,covar
,alpha
,&chisq
,
170 fitfn
[mfit
-1],&alamda
);
173 fprintf(stderr
,"%4d %10.5e %10.5e %10.5e",
174 j
,chisq
,alamda
,a
[1]);
176 fprintf(stderr
," %10.5e",a
[2]);
178 fprintf(stderr
," %10.5e",a
[3]);
179 fprintf(stderr
,"\n");
182 bCont
= ((fabs(ochisq
- chisq
) > fabs(ftol
*chisq
)) ||
183 ((ochisq
== chisq
)));
184 } while (bCont
&& (alamda
!= 0.0) && (j
< 50));
186 fprintf(stderr
,"\n");
188 /* Now get the covariance matrix out */
191 /* mrqmin(x-1,y-1,dy-1,nframes,a,ma,lista,mfit,covar,alpha,
192 * &chisq,fitfn[mfit-1],&alamda);
194 mrqmin_new(x
-1,y
-1,dy
-1,nframes
,a
,ia
,ma
,covar
,alpha
,&chisq
,
195 fitfn
[mfit
-1],&alamda
);
197 for(j
=0; (j
<mfit
); j
++) {
199 dparm
[j
] = covar
[j
+1][j
+1];
202 for(i
=0; (i
<ma
+1); i
++) {
212 real
do_lmfit(int ndata
,real c1
[],real sig
[],real dt
,
213 real begintimefit
,real endtimefit
,bool bVerbose
,int nfitparm
,
214 real fit
[],real fitparms
[],char *fix
)
220 real integral
,fittedfunc
;
222 real AA
=0,tau1
=0,tau2
=0,srAA
=0,srtau1
,srtau2
=0;
226 fprintf(stderr
,"There are %d points to fit %d vars!\n",
228 fprintf(stderr
,"Fit from %g thru %g, dt=%g\n",
229 begintimefit
,endtimefit
,dt
);
236 for(i
=0; (i
<ndata
); i
++) {
237 if ( ((dt
*i
) >= begintimefit
) && ((dt
*i
) <= endtimefit
) ) {
241 /* mrqmin does not like sig to be zero */
246 fprintf(stderr
,"j= %d, i= %d, x= %g, y= %g, dy= %g\n",
247 j
,i
,x
[j
],y
[j
],dy
[j
]);
254 fprintf(stderr
,"Not enough data points for fitting!\n");
261 parm
[0]=parm
[1]=parm
[2] = 1.0;
272 lmfit_exp(nfitpnts
,x
,y
,dy
,ftol
,parm
,dparm
,bVerbose
,nfitparm
,fix
);
289 /* Compute the integral from begintimefit to endtimefit
291 integral
=(tau1
*(myexp(begintimefit
,AA
, tau1
) -
292 myexp(endtimefit
, AA
, tau1
)) +
293 tau2
*(myexp(begintimefit
,1-AA
,tau2
) -
294 myexp(endtimefit
, 1-AA
,tau2
)));
296 /* Generate THE output */
298 fprintf(stderr
,"FIT: # points used in fit is: %d\n",nfitpnts
);
299 fprintf(stderr
,"FIT: %21s%21s%21s\n",
300 " A ","tau1 (ps) ","tau2 (ps) ");
301 fprintf(stderr
,"FIT: ------------------------------------------------------------\n");
302 fprintf(stderr
,"FIT: %8.3g +/- %8.3g%9.4g +/- %8.3g%8.3g +/- %8.3g\n",
303 AA
,srAA
,tau1
,srtau1
,tau2
,srtau2
);
304 fprintf(stderr
,"FIT: Integral (calc with fitted function) from %g to %g ps is: %g\n",
305 begintimefit
,endtimefit
,integral
);
307 sprintf(buf
,"test%d.xvg",nfitpnts
);
308 fp
= xvgropen(buf
,"C(t) + Fit to C(t)","Time (ps)","C(t)");
309 fprintf(fp
,"# AA = %g, tau1 = %g, tau2 = %g\n",AA
,tau1
,tau2
);
310 for(j
=0; (j
<ndata
); j
++) {
311 fittedfunc
= myexp(dt
*j
,AA
,tau1
) + myexp(dt
*j
,1-AA
,tau2
);
312 fprintf(fp
,"%10.5e %10.5e %10.5e\n",dt
*j
,c1
[j
],fittedfunc
);
316 /* Now copy the fitted func into the fit array, if not null */
318 for(i
=0; (i
<ndata
); i
++)
319 fit
[i
] = myexp(i
*dt
,AA
,tau1
) + myexp(i
*dt
,1-AA
,tau2
);
333 void do_expfit(int ndata
,real c1
[],real dt
,real begintimefit
,real endtimefit
)
337 real aa
,bb
,saa
,sbb
,A
,tau
,dA
,dtau
;
339 fprintf(stderr
,"Will fit data from %g (ps) to %g (ps).\n",
340 begintimefit
,endtimefit
);
342 snew(x
,ndata
); /* allocate the maximum necessary space */
347 for(i
=0; (i
<ndata
); i
++) {
348 if ( (dt
*i
>= begintimefit
) && (dt
*i
<= endtimefit
) ) {
352 fprintf(stderr
,"n= %d, i= %d, x= %g, y= %g\n",n
,i
,x
[n
],y
[n
]);
356 fprintf(stderr
,"# of data points used in the fit is : %d\n\n",n
);
357 expfit(n
,x
,y
,Dy
,&aa
,&saa
,&bb
,&sbb
);
363 fprintf(stderr
,"Fitted to y=exp(a+bx):\n");
364 fprintf(stderr
,"a = %10.5f\t b = %10.5f",aa
,bb
);
365 fprintf(stderr
,"\n");
366 fprintf(stderr
,"Fitted to y=Aexp(-x/tau):\n");
367 fprintf(stderr
,"A = %10.5f\t tau = %10.5f\n",A
,tau
);
368 fprintf(stderr
,"dA = %10.5f\t dtau = %10.5f\n",dA
,dtau
);
372 void expfit(int n
, real
*x
, real
*y
, real
*Dy
, real
*a
, real
*sa
,
375 real
*w
,*ly
,A
,SA
,B
,SB
;
377 real sum
,xbar
,ybar
,Sxx
,Sxy
,wr2
,chi2
,gamma
,Db
;
384 #define sqr(x) ((x)*(x))
390 /* Calculate weights and values of ln(y). */
392 w
[i
]=sqr(y
[i
]/Dy
[i
]);
396 /* The weighted averages of x and y: xbar and ybar. */
408 /* The centered product sums Sxx and Sxy, and hence A and B. */
412 Sxx
+=w
[i
]*sqr(x
[i
]-xbar
);
413 Sxy
+=w
[i
]*(x
[i
]-xbar
)*(ly
[i
]-ybar
);
418 /* Chi-squared (chi2) and gamma. */
422 wr2
=w
[i
]*sqr(ly
[i
]-A
-B
*x
[i
]);
424 gamma
+=wr2
*(x
[i
]-xbar
);
427 /* Refined values of A and B. Also SA and SB. */
430 A
-=ONEP5
*chi2
/sum
-xbar
*Db
;
431 SB
=sqrt((chi2
/(n
-2))/Sxx
);
432 SA
=SB
*sqrt(Sxx
/sum
+sqr(xbar
));