int gmx_dielectric(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] calculates frequency dependent dielectric constants", "from the autocorrelation function of the total dipole moment in", "your simulation. This ACF can be generated by [gmx-dipoles].", "The functional forms of the available functions are:[PAR]", "One parameter: y = [EXP]-a[SUB]1[sub] x[exp],[BR]", "Two parameters: y = a[SUB]2[sub] [EXP]-a[SUB]1[sub] x[exp],[BR]", "Three parameters: y = a[SUB]2[sub] [EXP]-a[SUB]1[sub] x[exp] + (1 - a[SUB]2[sub]) [EXP]-a[SUB]3[sub] x[exp].[BR]", "Start values for the fit procedure can be given on the command line.", "It is also possible to fix parameters at their start value, use [TT]-fix[tt]", "with the number of the parameter you want to fix.", "[PAR]", "Three output files are generated, the first contains the ACF,", "an exponential fit to it with 1, 2 or 3 parameters, and the", "numerical derivative of the combination data/fit.", "The second file contains the real and imaginary parts of the", "frequency-dependent dielectric constant, the last gives a plot", "known as the Cole-Cole plot, in which the imaginary", "component is plotted as a function of the real component.", "For a pure exponential relaxation (Debye relaxation) the latter", "plot should be one half of a circle." }; t_filenm fnm[] = { { efXVG, "-f", "dipcorr", ffREAD }, { efXVG, "-d", "deriv", ffWRITE }, { efXVG, "-o", "epsw", ffWRITE }, { efXVG, "-c", "cole", ffWRITE } }; #define NFILE asize(fnm) output_env_t oenv; int i, j, nx, ny, nxtail, eFitFn, nfitparm; real dt, integral, fitintegral, *fitparms, fac, rffac; double **yd; real **y; const char *legend[] = { "Correlation", "Std. Dev.", "Fit", "Combined", "Derivative" }; static int fix = 0, bFour = 0, bX = 1, nsmooth = 3; static real tendInt = 5.0, tbegin = 5.0, tend = 500.0; static real A = 0.5, tau1 = 10.0, tau2 = 1.0, eps0 = 80, epsRF = 78.5, tail = 500.0; real lambda; t_pargs pa[] = { { "-fft", FALSE, etBOOL, {&bFour}, "use fast fourier transform for correlation function" }, { "-x1", FALSE, etBOOL, {&bX}, "use first column as [IT]x[it]-axis rather than first data set" }, { "-eint", FALSE, etREAL, {&tendInt}, "Time to end the integration of the data and start to use the fit"}, { "-bfit", FALSE, etREAL, {&tbegin}, "Begin time of fit" }, { "-efit", FALSE, etREAL, {&tend}, "End time of fit" }, { "-tail", FALSE, etREAL, {&tail}, "Length of function including data and tail from fit" }, { "-A", FALSE, etREAL, {&A}, "Start value for fit parameter A" }, { "-tau1", FALSE, etREAL, {&tau1}, "Start value for fit parameter [GRK]tau[grk]1" }, { "-tau2", FALSE, etREAL, {&tau2}, "Start value for fit parameter [GRK]tau[grk]2" }, { "-eps0", FALSE, etREAL, {&eps0}, "[GRK]epsilon[grk]0 of your liquid" }, { "-epsRF", FALSE, etREAL, {&epsRF}, "[GRK]epsilon[grk] of the reaction field used in your simulation. A value of 0 means infinity." }, { "-fix", FALSE, etINT, {&fix}, "Fix parameters at their start values, A (2), tau1 (1), or tau2 (4)" }, { "-ffn", FALSE, etENUM, {s_ffn}, "Fit function" }, { "-nsmooth", FALSE, etINT, {&nsmooth}, "Number of points for smoothing" } }; if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } please_cite(stdout, "Spoel98a"); printf("WARNING: non-polarizable models can never yield an infinite\n" "dielectric constant that is different from 1. This is incorrect\n" "in the reference given above (Spoel98a).\n\n"); nx = read_xvg(opt2fn("-f", NFILE, fnm), &yd, &ny); dt = yd[0][1] - yd[0][0]; nxtail = min(tail/dt, nx); printf("Read data set containing %d colums and %d rows\n", ny, nx); printf("Assuming (from data) that timestep is %g, nxtail = %d\n", dt, nxtail); snew(y, 6); for (i = 0; (i < ny); i++) { snew(y[i], max(nx, nxtail)); } for (i = 0; (i < nx); i++) { y[0][i] = yd[0][i]; for (j = 1; (j < ny); j++) { y[j][i] = yd[j][i]; } } if (nxtail > nx) { for (i = nx; (i < nxtail); i++) { y[0][i] = dt*i+y[0][0]; for (j = 1; (j < ny); j++) { y[j][i] = 0.0; } } nx = nxtail; } /* We have read a file WITHOUT standard deviations, so we make our own... */ if (ny == 2) { printf("Creating standard deviation numbers ...\n"); srenew(y, 3); snew(y[2], nx); fac = 1.0/((real)nx); for (i = 0; (i < nx); i++) { y[2][i] = fac; } } eFitFn = sffn2effn(s_ffn); nfitparm = nfp_ffn[eFitFn]; snew(fitparms, 4); fitparms[0] = tau1; if (nfitparm > 1) { fitparms[1] = A; } if (nfitparm > 2) { fitparms[2] = tau2; } snew(y[3], nx); snew(y[4], nx); snew(y[5], nx); integral = print_and_integrate(NULL, calc_nbegin(nx, y[0], tbegin), dt, y[1], NULL, 1); integral += do_lmfit(nx, y[1], y[2], dt, y[0], tbegin, tend, oenv, TRUE, eFitFn, fitparms, fix); for (i = 0; i < nx; i++) { y[3][i] = fit_function(eFitFn, fitparms, y[0][i]); } if (epsRF == 0) { /* This means infinity! */ lambda = 0; rffac = 1; } else { lambda = (eps0 - 1.0)/(2*epsRF - 1.0); rffac = (2*epsRF+eps0)/(2*epsRF+1); } printf("DATA INTEGRAL: %5.1f, tauD(old) = %5.1f ps, " "tau_slope = %5.1f, tau_slope,D = %5.1f ps\n", integral, integral*rffac, fitparms[0], fitparms[0]*rffac); printf("tau_D from tau1 = %8.3g , eps(Infty) = %8.3f\n", fitparms[0]*(1 + fitparms[1]*lambda), 1 + ((1 - fitparms[1])*(eps0 - 1))/(1 + fitparms[1]*lambda)); fitintegral = numerical_deriv(nx, y[0], y[1], y[3], y[4], y[5], tendInt, nsmooth); printf("FIT INTEGRAL (tau_M): %5.1f, tau_D = %5.1f\n", fitintegral, fitintegral*rffac); /* Now we have the negative gradient of <Phi(0) Phi(t)> */ write_xvg(opt2fn("-d", NFILE, fnm), "Data", nx-1, 6, y, legend, oenv); /* Do FFT and analysis */ do_four(opt2fn("-o", NFILE, fnm), opt2fn("-c", NFILE, fnm), nx-1, y[0], y[5], eps0, epsRF, oenv); do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy"); do_view(oenv, opt2fn("-c", NFILE, fnm), NULL); do_view(oenv, opt2fn("-d", NFILE, fnm), "-nxy"); return 0; }
static void do_fit(FILE *out,int n,bool bYdy,int ny,real *x0,real **val, int npargs,t_pargs *ppa) { real *c1=NULL,*sig=NULL,*fitparm; real dt=0,tendfit,tbeginfit; int i,efitfn,nparm; efitfn = get_acffitfn(); nparm = nfp_ffn[efitfn]; fprintf(out,"Will fit to the following function:\n"); fprintf(out,"%s\n",longs_ffn[efitfn]); c1 = val[n]; if (bYdy) { c1 = val[n]; sig = val[n+1]; fprintf(out,"Using two columns as y and sigma values\n"); } else { snew(sig,ny); } if (opt2parg_bSet("-beginfit",npargs,ppa)) { tbeginfit = opt2parg_real("-beginfit",npargs,ppa); } else { tbeginfit = x0 ? x0[0] : 0; } if (opt2parg_bSet("-endfit",npargs,ppa)) { tendfit = opt2parg_real("-endfit",npargs,ppa); } else { tendfit = x0 ? x0[ny-1] : (ny-1)*dt; } snew(fitparm,nparm); switch(efitfn) { case effnEXP1: fitparm[0] = 0.5; break; case effnEXP2: fitparm[0] = 0.5; fitparm[1] = c1[0]; break; case effnEXP3: fitparm[0] = 1.0; fitparm[1] = 0.5*c1[0]; fitparm[2] = 10.0; break; case effnEXP5: fitparm[0] = fitparm[2] = 0.5*c1[0]; fitparm[1] = 10; fitparm[3] = 40; fitparm[4] = 0; break; case effnEXP7: fitparm[0] = fitparm[2] = fitparm[4] = 0.33*c1[0]; fitparm[1] = 1; fitparm[3] = 10; fitparm[5] = 100; fitparm[6] = 0; break; case effnEXP9: fitparm[0] = fitparm[2] = fitparm[4] = fitparm[6] = 0.25*c1[0]; fitparm[1] = 0.1; fitparm[3] = 1; fitparm[5] = 10; fitparm[7] = 100; fitparm[8] = 0; break; default: fprintf(out,"Warning: don't know how to initialize the parameters\n"); for(i=0; (i<nparm); i++) fitparm[i] = 1; } fprintf(out,"Starting parameters:\n"); for(i=0; (i<nparm); i++) fprintf(out,"a%-2d = %12.5e\n",i+1,fitparm[i]); if (do_lmfit(ny,c1,sig,dt,x0,tbeginfit,tendfit, bDebugMode(),efitfn,fitparm,0)) { for(i=0; (i<nparm); i++) fprintf(out,"a%-2d = %12.5e\n",i+1,fitparm[i]); } else { fprintf(out,"No solution was found\n"); } }
static void process_tcaf(int nframes, real dt, int nkc, real **tc, rvec *kfac, real rho, real wt, const char *fn_trans, const char *fn_tca, const char *fn_tc, const char *fn_tcf, const char *fn_cub, const char *fn_vk, const gmx_output_env_t *oenv) { FILE *fp, *fp_vk, *fp_cub = NULL; int nk, ntc; real **tcaf, **tcafc = NULL, eta, *sig; int i, j, k, kc; int ncorr; double fitparms[3]; nk = kset_c[nkc]; ntc = nk*NPK; if (fn_trans) { fp = xvgropen(fn_trans, "Transverse Current", "Time (ps)", "TC (nm/ps)", oenv); for (i = 0; i < nframes; i++) { fprintf(fp, "%g", i*dt); for (j = 0; j < ntc; j++) { fprintf(fp, " %g", tc[j][i]); } fprintf(fp, "\n"); } xvgrclose(fp); do_view(oenv, fn_trans, "-nxy"); } ncorr = (nframes+1)/2; if (ncorr > static_cast<int>(5*wt/dt+0.5)) { ncorr = static_cast<int>(5*wt/dt+0.5)+1; } snew(tcaf, nk); for (k = 0; k < nk; k++) { snew(tcaf[k], ncorr); } if (fn_cub) { snew(tcafc, nkc); for (k = 0; k < nkc; k++) { snew(tcafc[k], ncorr); } } snew(sig, ncorr); for (i = 0; i < ncorr; i++) { sig[i] = std::exp(0.5*i*dt/wt); } low_do_autocorr(fn_tca, oenv, "Transverse Current Autocorrelation Functions", nframes, ntc, ncorr, tc, dt, eacNormal, 1, FALSE, FALSE, FALSE, 0, 0, 0); do_view(oenv, fn_tca, "-nxy"); fp = xvgropen(fn_tc, "Transverse Current Autocorrelation Functions", "Time (ps)", "TCAF", oenv); for (i = 0; i < ncorr; i++) { kc = 0; fprintf(fp, "%g", i*dt); for (k = 0; k < nk; k++) { for (j = 0; j < NPK; j++) { tcaf[k][i] += tc[NPK*k+j][i]; } if (fn_cub) { for (j = 0; j < NPK; j++) { tcafc[kc][i] += tc[NPK*k+j][i]; } } if (i == 0) { fprintf(fp, " %g", 1.0); } else { tcaf[k][i] /= tcaf[k][0]; fprintf(fp, " %g", tcaf[k][i]); } if (k+1 == kset_c[kc+1]) { kc++; } } fprintf(fp, "\n"); } xvgrclose(fp); do_view(oenv, fn_tc, "-nxy"); if (fn_cub) { fp_cub = xvgropen(fn_cub, "TCAFs and fits", "Time (ps)", "TCAF", oenv); for (kc = 0; kc < nkc; kc++) { fprintf(fp_cub, "%g %g\n", 0.0, 1.0); for (i = 1; i < ncorr; i++) { tcafc[kc][i] /= tcafc[kc][0]; fprintf(fp_cub, "%g %g\n", i*dt, tcafc[kc][i]); } fprintf(fp_cub, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); tcafc[kc][0] = 1.0; } } fp_vk = xvgropen(fn_vk, "Fits", "k (nm\\S-1\\N)", "\\8h\\4 (10\\S-3\\N kg m\\S-1\\N s\\S-1\\N)", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp_vk, "@ s0 symbol 2\n"); fprintf(fp_vk, "@ s0 symbol color 1\n"); fprintf(fp_vk, "@ s0 linestyle 0\n"); if (fn_cub) { fprintf(fp_vk, "@ s1 symbol 3\n"); fprintf(fp_vk, "@ s1 symbol color 2\n"); } } fp = xvgropen(fn_tcf, "TCAF Fits", "Time (ps)", "", oenv); for (k = 0; k < nk; k++) { tcaf[k][0] = 1.0; fitparms[0] = 1; fitparms[1] = 1; do_lmfit(ncorr, tcaf[k], sig, dt, 0, 0, ncorr*dt, oenv, bDebugMode(), effnVAC, fitparms, 0, NULL); eta = 1000*fitparms[1]*rho/ (4*fitparms[0]*PICO*norm2(kfac[k])/(NANO*NANO)); fprintf(stdout, "k %6.3f tau %6.3f eta %8.5f 10^-3 kg/(m s)\n", norm(kfac[k]), fitparms[0], eta); fprintf(fp_vk, "%6.3f %g\n", norm(kfac[k]), eta); for (i = 0; i < ncorr; i++) { fprintf(fp, "%g %g\n", i*dt, fit_function(effnVAC, fitparms, i*dt)); } fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); } xvgrclose(fp); do_view(oenv, fn_tcf, "-nxy"); if (fn_cub) { fprintf(stdout, "Averaged over k-vectors:\n"); fprintf(fp_vk, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); for (k = 0; k < nkc; k++) { tcafc[k][0] = 1.0; fitparms[0] = 1; fitparms[1] = 1; do_lmfit(ncorr, tcafc[k], sig, dt, 0, 0, ncorr*dt, oenv, bDebugMode(), effnVAC, fitparms, 0, NULL); eta = 1000*fitparms[1]*rho/ (4*fitparms[0]*PICO*norm2(kfac[kset_c[k]])/(NANO*NANO)); fprintf(stdout, "k %6.3f tau %6.3f Omega %6.3f eta %8.5f 10^-3 kg/(m s)\n", norm(kfac[kset_c[k]]), fitparms[0], fitparms[1], eta); fprintf(fp_vk, "%6.3f %g\n", norm(kfac[kset_c[k]]), eta); for (i = 0; i < ncorr; i++) { fprintf(fp_cub, "%g %g\n", i*dt, fit_function(effnVAC, fitparms, i*dt)); } fprintf(fp_cub, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); } fprintf(fp_vk, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); xvgrclose(fp_cub); do_view(oenv, fn_cub, "-nxy"); } xvgrclose(fp_vk); do_view(oenv, fn_vk, "-nxy"); }
static void estimate_error(char *eefile,int nb_min,int resol,int n,int nset, double *av,double *sig,real **val,real dt, bool bFitAc,bool bSingleExpFit,bool bAllowNegLTCorr) { FILE *fp; int bs,prev_bs,nbs,nb; real spacing,nbr; int s,i,j; double blav,var; char **leg; real *tbs,*ybs,rtmp,dens,*fitsig,twooe,tau1_est,tau_sig; real fitparm[4]; real ee,a,tau1,tau2; if (n < 4) { fprintf(stdout,"The number of points is smaller than 4, can not make an error estimate\n"); return; } fp = xvgropen(eefile,"Error estimates", "Block size (time)","Error estimate"); if (bPrintXvgrCodes()) { fprintf(fp, "@ subtitle \"using block averaging, total time %g (%d points)\"\n", (n-1)*dt,n); } snew(leg,2*nset); xvgr_legend(fp,2*nset,leg); sfree(leg); spacing = pow(2,1.0/resol); snew(tbs,n); snew(ybs,n); snew(fitsig,n); for(s=0; s<nset; s++) { nbs = 0; prev_bs = 0; nbr = nb_min; while (nbr <= n) { bs = n/(int)nbr; if (bs != prev_bs) { nb = n/bs; var = 0; for(i=0; i<nb; i++) { blav=0; for (j=0; j<bs; j++) { blav += val[s][bs*i+j]; } var += sqr(av[s] - blav/bs); } tbs[nbs] = bs*dt; if (sig[s] == 0) { ybs[nbs] = 0; } else { ybs[nbs] = var/(nb*(nb-1.0))*(n*dt)/(sig[s]*sig[s]); } nbs++; } nbr *= spacing; nb = (int)(nbr+0.5); prev_bs = bs; } if (sig[s] == 0) { ee = 0; a = 1; tau1 = 0; tau2 = 0; } else { for(i=0; i<nbs/2; i++) { rtmp = tbs[i]; tbs[i] = tbs[nbs-1-i]; tbs[nbs-1-i] = rtmp; rtmp = ybs[i]; ybs[i] = ybs[nbs-1-i]; ybs[nbs-1-i] = rtmp; } /* The initial slope of the normalized ybs^2 is 1. * For a single exponential autocorrelation: ybs(tau1) = 2/e tau1 * From this we take our initial guess for tau1. */ twooe = 2/exp(1); i = -1; do { i++; tau1_est = tbs[i]; } while (i < nbs - 1 && (ybs[i] > ybs[i+1] || ybs[i] > twooe*tau1_est)); if (ybs[0] > ybs[1]) { fprintf(stdout,"Data set %d has strange time correlations:\n" "the std. error using single points is larger than that of blocks of 2 points\n" "The error estimate might be inaccurate, check the fit\n", s+1); /* Use the total time as tau for the fitting weights */ tau_sig = (n - 1)*dt; } else { tau_sig = tau1_est; } if (debug) { fprintf(debug,"set %d tau1 estimate %f\n",s+1,tau1_est); } /* Generate more or less appropriate sigma's, * also taking the density of points into account. */ for(i=0; i<nbs; i++) { if (i == 0) { dens = tbs[1]/tbs[0] - 1; } else if (i == nbs-1) { dens = tbs[nbs-1]/tbs[nbs-2] - 1; } else { dens = 0.5*(tbs[i+1]/tbs[i-1] - 1); } fitsig[i] = sqrt((tau_sig + tbs[i])/dens); } if (!bSingleExpFit) { fitparm[0] = tau1_est; fitparm[1] = 0.95; /* We set the initial guess for tau2 * to halfway between tau1_est and the total time (on log scale). */ fitparm[2] = sqrt(tau1_est*(n-1)*dt); do_lmfit(nbs,ybs,fitsig,0,tbs,0,dt*n,bDebugMode(),effnERREST,fitparm,0); fitparm[3] = 1-fitparm[1]; } if (bSingleExpFit || fitparm[0]<0 || fitparm[2]<0 || fitparm[1]<0 || (fitparm[1]>1 && !bAllowNegLTCorr) || fitparm[2]>(n-1)*dt) { if (!bSingleExpFit) { if (fitparm[2] > (n-1)*dt) { fprintf(stdout, "Warning: tau2 is longer than the length of the data (%g)\n" " the statistics might be bad\n", (n-1)*dt); } else { fprintf(stdout,"a fitted parameter is negative\n"); } fprintf(stdout,"invalid fit: e.e. %g a %g tau1 %g tau2 %g\n", sig[s]*anal_ee_inf(fitparm,n*dt), fitparm[1],fitparm[0],fitparm[2]); /* Do a fit with tau2 fixed at the total time. * One could also choose any other large value for tau2. */ fitparm[0] = tau1_est; fitparm[1] = 0.95; fitparm[2] = (n-1)*dt; fprintf(stderr,"Will fix tau2 at the total time: %g\n",fitparm[2]); do_lmfit(nbs,ybs,fitsig,0,tbs,0,dt*n,bDebugMode(),effnERREST,fitparm,4); fitparm[3] = 1-fitparm[1]; } if (bSingleExpFit || fitparm[0]<0 || fitparm[1]<0 || (fitparm[1]>1 && !bAllowNegLTCorr)) { if (!bSingleExpFit) { fprintf(stdout,"a fitted parameter is negative\n"); fprintf(stdout,"invalid fit: e.e. %g a %g tau1 %g tau2 %g\n", sig[s]*anal_ee_inf(fitparm,n*dt), fitparm[1],fitparm[0],fitparm[2]); } /* Do a single exponential fit */ fprintf(stderr,"Will use a single exponential fit for set %d\n",s+1); fitparm[0] = tau1_est; fitparm[1] = 1.0; fitparm[2] = 0.0; do_lmfit(nbs,ybs,fitsig,0,tbs,0,dt*n,bDebugMode(),effnERREST,fitparm,6); fitparm[3] = 1-fitparm[1]; } } ee = sig[s]*anal_ee_inf(fitparm,n*dt); a = fitparm[1]; tau1 = fitparm[0]; tau2 = fitparm[2]; } fprintf(stdout,"Set %3d: err.est. %g a %g tau1 %g tau2 %g\n", s+1,ee,a,tau1,tau2); fprintf(fp,"@ legend string %d \"av %f\"\n",2*s,av[s]); fprintf(fp,"@ legend string %d \"ee %6g\"\n", 2*s+1,sig[s]*anal_ee_inf(fitparm,n*dt)); for(i=0; i<nbs; i++) { fprintf(fp,"%g %g %g\n",tbs[i],sig[s]*sqrt(ybs[i]/(n*dt)), sig[s]*sqrt(fit_function(effnERREST,fitparm,tbs[i])/(n*dt))); } if (bFitAc) { int fitlen; real *ac,acint,ac_fit[4]; snew(ac,n); for(i=0; i<n; i++) { ac[i] = val[s][i] - av[s]; if (i > 0) fitsig[i] = sqrt(i); else fitsig[i] = 1; } low_do_autocorr(NULL,NULL,n,1,-1,&ac, dt,eacNormal,1,FALSE,TRUE, FALSE,0,0,effnNONE,0); fitlen = n/nb_min; /* Integrate ACF only up to fitlen/2 to avoid integrating noise */ acint = 0.5*ac[0]; for(i=1; i<=fitlen/2; i++) { acint += ac[i]; } acint *= dt; /* Generate more or less appropriate sigma's */ for(i=0; i<=fitlen; i++) { fitsig[i] = sqrt(acint + dt*i); } ac_fit[0] = 0.5*acint; ac_fit[1] = 0.95; ac_fit[2] = 10*acint; do_lmfit(n/nb_min,ac,fitsig,dt,0,0,fitlen*dt, bDebugMode(),effnEXP3,ac_fit,0); ac_fit[3] = 1 - ac_fit[1]; fprintf(stdout,"Set %3d: ac erest %g a %g tau1 %g tau2 %g\n", s+1,sig[s]*anal_ee_inf(ac_fit,n*dt), ac_fit[1],ac_fit[0],ac_fit[2]); fprintf(fp,"&\n"); for(i=0; i<nbs; i++) { fprintf(fp,"%g %g\n",tbs[i], sig[s]*sqrt(fit_function(effnERREST,ac_fit,tbs[i]))/(n*dt)); } sfree(ac); } if (s < nset-1) { fprintf(fp,"&\n"); } } sfree(fitsig); sfree(ybs); sfree(tbs); fclose(fp); }
real fit_acf(int ncorr, int fitfn, const gmx_output_env_t *oenv, gmx_bool bVerbose, real tbeginfit, real tendfit, real dt, real c1[], real *fit) { double fitparm[3]; double tStart, tail_corr, sum, sumtot = 0, c_start, ct_estimate; real *sig; int i, j, jmax, nf_int; gmx_bool bPrint; bPrint = bVerbose || bDebugMode(); if (bPrint) { printf("COR:\n"); } if (tendfit <= 0) { tendfit = ncorr*dt; } nf_int = std::min(ncorr, (int)(tendfit/dt)); sum = print_and_integrate(debug, nf_int, dt, c1, NULL, 1); if (bPrint) { printf("COR: Correlation time (plain integral from %6.3f to %6.3f ps) = %8.5f ps\n", 0.0, dt*nf_int, sum); printf("COR: Relaxation times are computed as fit to an exponential:\n"); printf("COR: %s\n", effnDescription(fitfn)); printf("COR: Fit to correlation function from %6.3f ps to %6.3f ps, results in a\n", tbeginfit, std::min(ncorr*dt, tendfit)); } tStart = 0; if (bPrint) { printf("COR:%11s%11s%11s%11s%11s%11s%11s\n", "Fit from", "Integral", "Tail Value", "Sum (ps)", " a1 (ps)", (effnNparams(fitfn) >= 2) ? " a2 ()" : "", (effnNparams(fitfn) >= 3) ? " a3 (ps)" : ""); } snew(sig, ncorr); if (tbeginfit > 0) { jmax = 3; } else { jmax = 1; } for (j = 0; ((j < jmax) && (tStart < tendfit) && (tStart < ncorr*dt)); j++) { /* Estimate the correlation time for better fitting */ c_start = -1; ct_estimate = 0; for (i = 0; (i < ncorr) && (dt*i < tStart || c1[i] > 0); i++) { if (c_start < 0) { if (dt*i >= tStart) { c_start = c1[i]; ct_estimate = 0.5*c1[i]; } } else { ct_estimate += c1[i]; } } if (c_start > 0) { ct_estimate *= dt/c_start; } else { /* The data is strange, so we need to choose somehting */ ct_estimate = tendfit; } if (debug) { fprintf(debug, "tStart %g ct_estimate: %g\n", tStart, ct_estimate); } if (fitfn == effnEXPEXP) { fitparm[0] = 0.002*ncorr*dt; fitparm[1] = 0.95; fitparm[2] = 0.2*ncorr*dt; } else { /* Good initial guess, this increases the probability of convergence */ fitparm[0] = ct_estimate; fitparm[1] = 1.0; fitparm[2] = 1.0; } /* Generate more or less appropriate sigma's */ for (i = 0; i < ncorr; i++) { sig[i] = sqrt(ct_estimate+dt*i); } nf_int = std::min(ncorr, (int)((tStart+1e-4)/dt)); sum = print_and_integrate(debug, nf_int, dt, c1, NULL, 1); tail_corr = do_lmfit(ncorr, c1, sig, dt, NULL, tStart, tendfit, oenv, bDebugMode(), fitfn, fitparm, 0, NULL); sumtot = sum+tail_corr; if (fit && ((jmax == 1) || (j == 1))) { double mfp[3]; for (i = 0; (i < 3); i++) { mfp[i] = fitparm[i]; } for (i = 0; (i < ncorr); i++) { fit[i] = lmcurves[fitfn](i*dt, mfp); } } if (bPrint) { printf("COR:%11.4e%11.4e%11.4e%11.4e", tStart, sum, tail_corr, sumtot); for (i = 0; (i < effnNparams(fitfn)); i++) { printf(" %11.4e", fitparm[i]); } printf("\n"); } tStart += tbeginfit; } sfree(sig); return sumtot; }
static void do_fit(FILE *out, int n, gmx_bool bYdy, int ny, real *x0, real **val, int npargs, t_pargs *ppa, const gmx_output_env_t *oenv, const char *fn_fitted) { real *c1 = NULL, *sig = NULL; double *fitparm; real tendfit, tbeginfit; int i, efitfn, nparm; efitfn = get_acffitfn(); nparm = effnNparams(efitfn); fprintf(out, "Will fit to the following function:\n"); fprintf(out, "%s\n", effnDescription(efitfn)); c1 = val[n]; if (bYdy) { c1 = val[n]; sig = val[n+1]; fprintf(out, "Using two columns as y and sigma values\n"); } else { snew(sig, ny); } if (opt2parg_bSet("-beginfit", npargs, ppa)) { tbeginfit = opt2parg_real("-beginfit", npargs, ppa); } else { tbeginfit = x0[0]; } if (opt2parg_bSet("-endfit", npargs, ppa)) { tendfit = opt2parg_real("-endfit", npargs, ppa); } else { tendfit = x0[ny-1]; } snew(fitparm, nparm); switch (efitfn) { case effnEXP1: fitparm[0] = 0.5; break; case effnEXP2: fitparm[0] = 0.5; fitparm[1] = c1[0]; break; case effnEXPEXP: fitparm[0] = 1.0; fitparm[1] = 0.5*c1[0]; fitparm[2] = 10.0; break; case effnEXP5: fitparm[0] = fitparm[2] = 0.5*c1[0]; fitparm[1] = 10; fitparm[3] = 40; fitparm[4] = 0; break; case effnEXP7: fitparm[0] = fitparm[2] = fitparm[4] = 0.33*c1[0]; fitparm[1] = 1; fitparm[3] = 10; fitparm[5] = 100; fitparm[6] = 0; break; case effnEXP9: fitparm[0] = fitparm[2] = fitparm[4] = fitparm[6] = 0.25*c1[0]; fitparm[1] = 0.1; fitparm[3] = 1; fitparm[5] = 10; fitparm[7] = 100; fitparm[8] = 0; break; default: fprintf(out, "Warning: don't know how to initialize the parameters\n"); for (i = 0; (i < nparm); i++) { fitparm[i] = 1; } } fprintf(out, "Starting parameters:\n"); for (i = 0; (i < nparm); i++) { fprintf(out, "a%-2d = %12.5e\n", i+1, fitparm[i]); } if (do_lmfit(ny, c1, sig, 0, x0, tbeginfit, tendfit, oenv, bDebugMode(), efitfn, fitparm, 0, fn_fitted) > 0) { for (i = 0; (i < nparm); i++) { fprintf(out, "a%-2d = %12.5e\n", i+1, fitparm[i]); } } else { fprintf(out, "No solution was found\n"); } }
static void interfaces_txy (real ****Densmap, int xslices, int yslices, int zslices, int tblocks, real binwidth, int method, real dens1, real dens2, t_interf ****intf1, t_interf ****intf2, const gmx_output_env_t *oenv) { /*Returns two pointers to 3D arrays of t_interf structs containing (position,thickness) of the interface(s)*/ FILE *xvg; real *zDensavg; /* zDensavg[z]*/ int i, j, k, n; int xysize; int ndx1, ndx2, *zperm; real densmid; real splitpoint, startpoint, endpoint; real *sigma1, *sigma2; double beginfit1[4]; double beginfit2[4]; double *fit1 = NULL, *fit2 = NULL; const double *avgfit1; const double *avgfit2; const real onehalf = 1.00/2.00; t_interf ***int1 = NULL, ***int2 = NULL; /*Interface matrices [t][x,y] - last index in row-major order*/ /*Create int1(t,xy) and int2(t,xy) arrays with correct number of interf_t elements*/ xysize = xslices*yslices; snew(int1, tblocks); snew(int2, tblocks); for (i = 0; i < tblocks; i++) { snew(int1[i], xysize); snew(int2[i], xysize); for (j = 0; j < xysize; j++) { snew(int1[i][j], 1); snew(int2[i][j], 1); init_interf(int1[i][j]); init_interf(int2[i][j]); } } if (method == methBISECT) { densmid = onehalf*(dens1+dens2); snew(zperm, zslices); for (n = 0; n < tblocks; n++) { for (i = 0; i < xslices; i++) { for (j = 0; j < yslices; j++) { rangeArray(zperm, zslices); /*reset permutation array to identity*/ /*Binsearch returns slice-nr where the order param is <= setpoint sgmid*/ ndx1 = start_binsearch(Densmap[n][i][j], zperm, 0, zslices/2-1, densmid, 1); ndx2 = start_binsearch(Densmap[n][i][j], zperm, zslices/2, zslices-1, densmid, -1); /* Linear interpolation (for use later if time allows) * rho_1s= Densmap[n][i][j][zperm[ndx1]] * rho_1e =Densmap[n][i][j][zperm[ndx1+1]] - in worst case might be far off * rho_2s =Densmap[n][i][j][zperm[ndx2+1]] * rho_2e =Densmap[n][i][j][zperm[ndx2]] * For 1st interface we have: densl= Densmap[n][i][j][zperm[ndx1]]; densr= Densmap[n][i][j][zperm[ndx1+1]]; alpha=(densmid-densl)/(densr-densl); deltandx=zperm[ndx1+1]-zperm[ndx1]; if(debug){ printf("Alpha, Deltandx %f %i\n", alpha,deltandx); } if(abs(alpha)>1.0 || abs(deltandx)>3){ pos=zperm[ndx1]; spread=-1; } else { pos=zperm[ndx1]+alpha*deltandx; spread=binwidth*deltandx; } * For the 2nd interface can use the same formulation, since alpha should become negative ie: * alpha=(densmid-Densmap[n][i][j][zperm[ndx2]])/(Densmap[n][i][j][zperm[nxd2+1]]-Densmap[n][i][j][zperm[ndx2]]); * deltandx=zperm[ndx2+1]-zperm[ndx2]; * pos=zperm[ndx2]+alpha*deltandx; */ /*After filtering we use the direct approach */ int1[n][j+(i*yslices)]->Z = (zperm[ndx1]+onehalf)*binwidth; int1[n][j+(i*yslices)]->t = binwidth; int2[n][j+(i*yslices)]->Z = (zperm[ndx2]+onehalf)*binwidth; int2[n][j+(i*yslices)]->t = binwidth; } } } } if (method == methFUNCFIT) { /*Assume a box divided in 2 along midpoint of z for starters*/ startpoint = 0.0; endpoint = binwidth*zslices; splitpoint = (startpoint+endpoint)/2.0; /*Initial fit proposals*/ beginfit1[0] = dens1; beginfit1[1] = dens2; beginfit1[2] = (splitpoint/2); beginfit1[3] = 0.5; beginfit2[0] = dens2; beginfit2[1] = dens1; beginfit2[2] = (3*splitpoint/2); beginfit2[3] = 0.5; snew(zDensavg, zslices); snew(sigma1, zslices); snew(sigma2, zslices); for (k = 0; k < zslices; k++) { sigma1[k] = sigma2[k] = 1; } /*Calculate average density along z - avoid smoothing by using coarse-grained-mesh*/ for (k = 0; k < zslices; k++) { for (n = 0; n < tblocks; n++) { for (i = 0; i < xslices; i++) { for (j = 0; j < yslices; j++) { zDensavg[k] += (Densmap[n][i][j][k]/(xslices*yslices*tblocks)); } } } } if (debug) { xvg = xvgropen("DensprofileonZ.xvg", "Averaged Densityprofile on Z", "z[nm]", "Density[kg/m^3]", oenv); for (k = 0; k < zslices; k++) { fprintf(xvg, "%4f.3 %8f.4\n", k*binwidth, zDensavg[k]); } xvgrclose(xvg); } /*Fit average density in z over whole trajectory to obtain tentative fit-parameters in fit1 and fit2*/ /*Fit 1st half of box*/ do_lmfit(zslices, zDensavg, sigma1, binwidth, NULL, startpoint, splitpoint, oenv, FALSE, effnERF, beginfit1, 8, NULL); /*Fit 2nd half of box*/ do_lmfit(zslices, zDensavg, sigma2, binwidth, NULL, splitpoint, endpoint, oenv, FALSE, effnERF, beginfit2, 8, NULL); /*Initialise the const arrays for storing the average fit parameters*/ avgfit1 = beginfit1; avgfit2 = beginfit2; /*Now do fit over each x y and t slice to get Zint(x,y,t) - loop is very large, we potentially should average over time directly*/ for (n = 0; n < tblocks; n++) { for (i = 0; i < xslices; i++) { for (j = 0; j < yslices; j++) { /*Reinitialise fit for each mesh-point*/ srenew(fit1, 4); srenew(fit2, 4); for (k = 0; k < 4; k++) { fit1[k] = avgfit1[k]; fit2[k] = avgfit2[k]; } /*Now fit and store in structures in row-major order int[n][i][j]*/ do_lmfit(zslices, Densmap[n][i][j], sigma1, binwidth, NULL, startpoint, splitpoint, oenv, FALSE, effnERF, fit1, 0, NULL); int1[n][j+(yslices*i)]->Z = fit1[2]; int1[n][j+(yslices*i)]->t = fit1[3]; do_lmfit(zslices, Densmap[n][i][j], sigma2, binwidth, NULL, splitpoint, endpoint, oenv, FALSE, effnERF, fit2, 0, NULL); int2[n][j+(yslices*i)]->Z = fit2[2]; int2[n][j+(yslices*i)]->t = fit2[3]; } } } } *intf1 = int1; *intf2 = int2; }
real fit_acf(int ncorr,int fitfn,const output_env_t oenv,gmx_bool bVerbose, real tbeginfit,real tendfit,real dt,real c1[],real *fit) { real fitparm[3]; real tStart,tail_corr,sum,sumtot=0,ct_estimate,*sig; int i,j,jmax,nf_int; gmx_bool bPrint; bPrint = bVerbose || bDebugMode(); if (bPrint) printf("COR:\n"); if (tendfit <= 0) tendfit = ncorr*dt; nf_int = min(ncorr,(int)(tendfit/dt)); sum = print_and_integrate(debug,nf_int,dt,c1,NULL,1); /* Estimate the correlation time for better fitting */ ct_estimate = 0.5*c1[0]; for(i=1; (i<ncorr) && (c1[i]>0); i++) ct_estimate += c1[i]; ct_estimate *= dt/c1[0]; if (bPrint) { printf("COR: Correlation time (plain integral from %6.3f to %6.3f ps) = %8.5f ps\n", 0.0,dt*nf_int,sum); printf("COR: Relaxation times are computed as fit to an exponential:\n"); printf("COR: %s\n",longs_ffn[fitfn]); printf("COR: Fit to correlation function from %6.3f ps to %6.3f ps, results in a\n",tbeginfit,min(ncorr*dt,tendfit)); } tStart = 0; if (bPrint) printf("COR:%11s%11s%11s%11s%11s%11s%11s\n", "Fit from","Integral","Tail Value","Sum (ps)"," a1 (ps)", (nfp_ffn[fitfn]>=2) ? " a2 ()" : "", (nfp_ffn[fitfn]>=3) ? " a3 (ps)" : ""); if (tbeginfit > 0) jmax = 3; else jmax = 1; if (fitfn == effnEXP3) { fitparm[0] = 0.002*ncorr*dt; fitparm[1] = 0.95; fitparm[2] = 0.2*ncorr*dt; } else { /* Good initial guess, this increases the probability of convergence */ fitparm[0] = ct_estimate; fitparm[1] = 1.0; fitparm[2] = 1.0; } /* Generate more or less appropriate sigma's */ snew(sig,ncorr); for(i=0; i<ncorr; i++) sig[i] = sqrt(ct_estimate+dt*i); for(j=0; ((j<jmax) && (tStart < tendfit)); j++) { /* Use the previous fitparm as starting values for the next fit */ nf_int = min(ncorr,(int)((tStart+1e-4)/dt)); sum = print_and_integrate(debug,nf_int,dt,c1,NULL,1); tail_corr = do_lmfit(ncorr,c1,sig,dt,NULL,tStart,tendfit,oenv, bDebugMode(),fitfn,fitparm,0); sumtot = sum+tail_corr; if (fit && ((jmax == 1) || (j == 1))) for(i=0; (i<ncorr); i++) fit[i] = fit_function(fitfn,fitparm,i*dt); if (bPrint) { printf("COR:%11.4e%11.4e%11.4e%11.4e",tStart,sum,tail_corr,sumtot); for(i=0; (i<nfp_ffn[fitfn]); i++) printf(" %11.4e",fitparm[i]); printf("\n"); } tStart += tbeginfit; } sfree(sig); return sumtot; }