inline static void calc_new_pts_normal(double (*calc_x)(), double (*calc_y)(), double (*calc_z)(), t_vec3 **arg) { t_vec3 *d; t_vec3 *ori; t_vec3 tmp; t_intersect inter; d = arg[0]; ori = arg[1]; update_inter_normal(&inter, ori, 0.000000001, 0.000000001); inter.pos.z = -(d[0].x * (inter.pos.x - ori->x) + d[0].y * (inter.pos.y - ori->y)) / d[0].z + ori->z; calc_tmp_normal(&tmp, &inter); d[1].x = calc_x(&inter, tmp); d[1].y = calc_y(&inter, tmp); d[1].z = calc_z(&inter, tmp); update_inter_normal(&inter, ori, -0.000000001, -0.000000002); inter.pos.z = -(d[0].x * (inter.pos.x - ori->x) + d[0].y * (inter.pos.y - ori->y)) / d[0].z + ori->z; calc_tmp_normal(&tmp, &inter); d[2].x = calc_x(&inter, tmp); d[2].y = calc_y(&inter, tmp); d[2].z = calc_z(&inter, tmp); }
si3::Coor3 Triangler::get_random() const { si3::Coor3 coor; coor.z = 0.0f; int type = fw::xrandom() % 4; if (type==0) { coor.x = 11.0f; coor.y = calc_y(); } else if (type == 1) { coor.x = -11.0f; coor.y = calc_y(); } else if (type == 2) { coor.x = calc_x(); coor.y = 7.0f; } else if (type == 3) { coor.x = calc_x(); coor.y = -7.0f; } return coor; }
void calc_normale(double (*calc_x)(), double (*calc_y)(), double (*calc_z)(), t_intersect *inter) { t_vec3 d[3]; t_vec3 v[2]; t_vec3 tmp; calc_tmp_normal(&tmp, inter); d[0].x = calc_x(inter, tmp); d[0].y = calc_y(inter, tmp); d[0].z = calc_z(inter, tmp); calc_new_pts_normal(calc_x, calc_y, calc_z, (t_vec3*[2]){d, &inter->pos});
static void dump_fy(output_env_t oenv, real toler) { FILE *fp; double Delta, f, y, DD; const char *leg[] = { "f", "fy", "y" }; DD = pow(10.0, 0.125); fp = xvgropen("fy.xvg", "Fig. 2, Lin2003a", "Delta", "y or fy", oenv); xvgr_legend(fp, asize(leg), leg, oenv); fprintf(fp, "@ world 1e-05, 0, 1000, 1\n"); fprintf(fp, "@ xaxes scale Logarithmic\n"); for (Delta = 1e-5; (Delta <= 1000); Delta *= DD) { f = calc_fluidicity(Delta, toler); y = calc_y(f, Delta, toler); fprintf(fp, "%10g %10g %10g %10g\n", Delta, f, f*y, y); } xvgrclose(fp); }
int gmx_dos(int argc, char *argv[]) { const char *desc[] = { "[TT]g_dos[tt] computes the Density of States from a simulations.", "In order for this to be meaningful the velocities must be saved", "in the trajecotry with sufficiently high frequency such as to cover", "all vibrations. For flexible systems that would be around a few fs", "between saving. Properties based on the DoS are printed on the", "standard output." }; const char *bugs[] = { "This program needs a lot of memory: total usage equals the number of atoms times 3 times number of frames times 4 (or 8 when run in double precision)." }; FILE *fp, *fplog; t_topology top; int ePBC = -1; t_trxframe fr; matrix box; int gnx; char title[256]; real t0, t1, m; t_trxstatus *status; int nV, nframes, n_alloc, i, j, k, l, fftcode, Nmol, Natom; double rho, dt, V2sum, Vsum, V, tmass, dostot, dos2, dosabs; real **c1, **dos, mi, beta, bfac, *nu, *tt, stddev, c1j; output_env_t oenv; gmx_fft_t fft; double cP, S, A, E, DiffCoeff, Delta, f, y, z, sigHS, Shs, Sig, DoS0, recip_fac; double wCdiff, wSdiff, wAdiff, wEdiff; static gmx_bool bVerbose = TRUE, bAbsolute = FALSE, bNormalize = FALSE; static gmx_bool bRecip = FALSE, bDump = FALSE; static real Temp = 298.15, toler = 1e-6; t_pargs pa[] = { { "-v", FALSE, etBOOL, {&bVerbose}, "Be loud and noisy." }, { "-recip", FALSE, etBOOL, {&bRecip}, "Use cm^-1 on X-axis instead of 1/ps for DoS plots." }, { "-abs", FALSE, etBOOL, {&bAbsolute}, "Use the absolute value of the Fourier transform of the VACF as the Density of States. Default is to use the real component only" }, { "-normdos", FALSE, etBOOL, {&bNormalize}, "Normalize the DoS such that it adds up to 3N. This is a hack that should not be necessary." }, { "-T", FALSE, etREAL, {&Temp}, "Temperature in the simulation" }, { "-toler", FALSE, etREAL, {&toler}, "[HIDDEN]Tolerance when computing the fluidicity using bisection algorithm" }, { "-dump", FALSE, etBOOL, {&bDump}, "[HIDDEN]Dump the y/fy plot corresponding to Fig. 2 inLin2003a and the and the weighting functions corresponding to Fig. 1 in Berens1983a." } }; t_filenm fnm[] = { { efTRN, "-f", NULL, ffREAD }, { efTPX, "-s", NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, "-vacf", "vacf", ffWRITE }, { efXVG, "-mvacf", "mvacf", ffWRITE }, { efXVG, "-dos", "dos", ffWRITE }, { efLOG, "-g", "dos", ffWRITE }, }; #define NFILE asize(fnm) int npargs; t_pargs *ppa; const char *DoSlegend[] = { "DoS(v)", "DoS(v)[Solid]", "DoS(v)[Diff]" }; npargs = asize(pa); ppa = add_acf_pargs(&npargs, pa); parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE, NFILE, fnm, npargs, ppa, asize(desc), desc, asize(bugs), bugs, &oenv); beta = 1/(Temp*BOLTZ); if (bDump) { printf("Dumping reference figures. Thanks for your patience.\n"); dump_fy(oenv, toler); dump_w(oenv, beta); exit(0); } fplog = gmx_fio_fopen(ftp2fn(efLOG, NFILE, fnm), "w"); fprintf(fplog, "Doing density of states analysis based on trajectory.\n"); please_cite(fplog, "Pascal2011a"); please_cite(fplog, "Caleman2011b"); read_tps_conf(ftp2fn(efTPX, NFILE, fnm), title, &top, &ePBC, NULL, NULL, box, TRUE); V = det(box); tmass = 0; for (i = 0; (i < top.atoms.nr); i++) { tmass += top.atoms.atom[i].m; } Natom = top.atoms.nr; Nmol = top.mols.nr; gnx = Natom*DIM; /* Correlation stuff */ snew(c1, gnx); for (i = 0; (i < gnx); i++) { c1[i] = NULL; } read_first_frame(oenv, &status, ftp2fn(efTRN, NFILE, fnm), &fr, TRX_NEED_V); t0 = fr.time; n_alloc = 0; nframes = 0; Vsum = V2sum = 0; nV = 0; do { if (fr.bBox) { V = det(fr.box); V2sum += V*V; Vsum += V; nV++; } if (nframes >= n_alloc) { n_alloc += 100; for (i = 0; i < gnx; i++) { srenew(c1[i], n_alloc); } } for (i = 0; i < gnx; i += DIM) { c1[i+XX][nframes] = fr.v[i/DIM][XX]; c1[i+YY][nframes] = fr.v[i/DIM][YY]; c1[i+ZZ][nframes] = fr.v[i/DIM][ZZ]; } t1 = fr.time; nframes++; } while (read_next_frame(oenv, status, &fr)); close_trj(status); dt = (t1-t0)/(nframes-1); if (nV > 0) { V = Vsum/nV; } if (bVerbose) { printf("Going to do %d fourier transforms of length %d. Hang on.\n", gnx, nframes); } low_do_autocorr(NULL, oenv, NULL, nframes, gnx, nframes, c1, dt, eacNormal, 0, FALSE, FALSE, FALSE, -1, -1, 0, 0); snew(dos, DOS_NR); for (j = 0; (j < DOS_NR); j++) { snew(dos[j], nframes+4); } if (bVerbose) { printf("Going to merge the ACFs into the mass-weighted and plain ACF\n"); } for (i = 0; (i < gnx); i += DIM) { mi = top.atoms.atom[i/DIM].m; for (j = 0; (j < nframes/2); j++) { c1j = (c1[i+XX][j] + c1[i+YY][j] + c1[i+ZZ][j]); dos[VACF][j] += c1j/Natom; dos[MVACF][j] += mi*c1j; } } fp = xvgropen(opt2fn("-vacf", NFILE, fnm), "Velocity ACF", "Time (ps)", "C(t)", oenv); snew(tt, nframes/2); for (j = 0; (j < nframes/2); j++) { tt[j] = j*dt; fprintf(fp, "%10g %10g\n", tt[j], dos[VACF][j]); } xvgrclose(fp); fp = xvgropen(opt2fn("-mvacf", NFILE, fnm), "Mass-weighted velocity ACF", "Time (ps)", "C(t)", oenv); for (j = 0; (j < nframes/2); j++) { fprintf(fp, "%10g %10g\n", tt[j], dos[MVACF][j]); } xvgrclose(fp); if ((fftcode = gmx_fft_init_1d_real(&fft, nframes/2, GMX_FFT_FLAG_NONE)) != 0) { gmx_fatal(FARGS, "gmx_fft_init_1d_real returned %d", fftcode); } if ((fftcode = gmx_fft_1d_real(fft, GMX_FFT_REAL_TO_COMPLEX, (void *)dos[MVACF], (void *)dos[DOS])) != 0) { gmx_fatal(FARGS, "gmx_fft_1d_real returned %d", fftcode); } /* First compute the DoS */ /* Magic factor of 8 included now. */ bfac = 8*dt*beta/2; dos2 = 0; snew(nu, nframes/4); for (j = 0; (j < nframes/4); j++) { nu[j] = 2*j/(t1-t0); dos2 += sqr(dos[DOS][2*j]) + sqr(dos[DOS][2*j+1]); if (bAbsolute) { dos[DOS][j] = bfac*sqrt(sqr(dos[DOS][2*j]) + sqr(dos[DOS][2*j+1])); } else { dos[DOS][j] = bfac*dos[DOS][2*j]; } } /* Normalize it */ dostot = evaluate_integral(nframes/4, nu, dos[DOS], NULL, nframes/4, &stddev); if (bNormalize) { for (j = 0; (j < nframes/4); j++) { dos[DOS][j] *= 3*Natom/dostot; } } /* Now analyze it */ DoS0 = dos[DOS][0]; /* Note this eqn. is incorrect in Pascal2011a! */ Delta = ((2*DoS0/(9*Natom))*sqrt(M_PI*BOLTZ*Temp*Natom/tmass)* pow((Natom/V), 1.0/3.0)*pow(6/M_PI, 2.0/3.0)); f = calc_fluidicity(Delta, toler); y = calc_y(f, Delta, toler); z = calc_compress(y); Sig = BOLTZ*(5.0/2.0+log(2*M_PI*BOLTZ*Temp/(sqr(PLANCK))*V/(f*Natom))); Shs = Sig+calc_Shs(f, y); rho = (tmass*AMU)/(V*NANO*NANO*NANO); sigHS = pow(6*y*V/(M_PI*Natom), 1.0/3.0); fprintf(fplog, "System = \"%s\"\n", title); fprintf(fplog, "Nmol = %d\n", Nmol); fprintf(fplog, "Natom = %d\n", Natom); fprintf(fplog, "dt = %g ps\n", dt); fprintf(fplog, "tmass = %g amu\n", tmass); fprintf(fplog, "V = %g nm^3\n", V); fprintf(fplog, "rho = %g g/l\n", rho); fprintf(fplog, "T = %g K\n", Temp); fprintf(fplog, "beta = %g mol/kJ\n", beta); fprintf(fplog, "\nDoS parameters\n"); fprintf(fplog, "Delta = %g\n", Delta); fprintf(fplog, "fluidicity = %g\n", f); fprintf(fplog, "hard sphere packing fraction = %g\n", y); fprintf(fplog, "hard sphere compressibility = %g\n", z); fprintf(fplog, "ideal gas entropy = %g\n", Sig); fprintf(fplog, "hard sphere entropy = %g\n", Shs); fprintf(fplog, "sigma_HS = %g nm\n", sigHS); fprintf(fplog, "DoS0 = %g\n", DoS0); fprintf(fplog, "Dos2 = %g\n", dos2); fprintf(fplog, "DoSTot = %g\n", dostot); /* Now compute solid (2) and diffusive (3) components */ fp = xvgropen(opt2fn("-dos", NFILE, fnm), "Density of states", bRecip ? "E (cm\\S-1\\N)" : "\\f{12}n\\f{4} (1/ps)", "\\f{4}S(\\f{12}n\\f{4})", oenv); xvgr_legend(fp, asize(DoSlegend), DoSlegend, oenv); recip_fac = bRecip ? (1e7/SPEED_OF_LIGHT) : 1.0; for (j = 0; (j < nframes/4); j++) { dos[DOS_DIFF][j] = DoS0/(1+sqr(DoS0*M_PI*nu[j]/(6*f*Natom))); dos[DOS_SOLID][j] = dos[DOS][j]-dos[DOS_DIFF][j]; fprintf(fp, "%10g %10g %10g %10g\n", recip_fac*nu[j], dos[DOS][j]/recip_fac, dos[DOS_SOLID][j]/recip_fac, dos[DOS_DIFF][j]/recip_fac); } xvgrclose(fp); /* Finally analyze the results! */ wCdiff = 0.5; wSdiff = Shs/(3*BOLTZ); /* Is this correct? */ wEdiff = 0.5; wAdiff = wEdiff-wSdiff; for (j = 0; (j < nframes/4); j++) { dos[DOS_CP][j] = (dos[DOS_DIFF][j]*wCdiff + dos[DOS_SOLID][j]*wCsolid(nu[j], beta)); dos[DOS_S][j] = (dos[DOS_DIFF][j]*wSdiff + dos[DOS_SOLID][j]*wSsolid(nu[j], beta)); dos[DOS_A][j] = (dos[DOS_DIFF][j]*wAdiff + dos[DOS_SOLID][j]*wAsolid(nu[j], beta)); dos[DOS_E][j] = (dos[DOS_DIFF][j]*wEdiff + dos[DOS_SOLID][j]*wEsolid(nu[j], beta)); } DiffCoeff = evaluate_integral(nframes/2, tt, dos[VACF], NULL, nframes/2, &stddev); DiffCoeff = 1000*DiffCoeff/3.0; fprintf(fplog, "Diffusion coefficient from VACF %g 10^-5 cm^2/s\n", DiffCoeff); fprintf(fplog, "Diffusion coefficient from DoS %g 10^-5 cm^2/s\n", 1000*DoS0/(12*tmass*beta)); cP = BOLTZ * evaluate_integral(nframes/4, nu, dos[DOS_CP], NULL, nframes/4, &stddev); fprintf(fplog, "Heat capacity %g J/mol K\n", 1000*cP/Nmol); /* S = BOLTZ * evaluate_integral(nframes/4,nu,dos[DOS_S],NULL, nframes/4,&stddev); fprintf(fplog,"Entropy %g J/mol K\n",1000*S/Nmol); A = BOLTZ * evaluate_integral(nframes/4,nu,dos[DOS_A],NULL, nframes/4,&stddev); fprintf(fplog,"Helmholtz energy %g kJ/mol\n",A/Nmol); E = BOLTZ * evaluate_integral(nframes/4,nu,dos[DOS_E],NULL, nframes/4,&stddev); fprintf(fplog,"Internal energy %g kJ/mol\n",E/Nmol); */ fprintf(fplog, "\nArrivederci!\n"); gmx_fio_fclose(fplog); do_view(oenv, ftp2fn(efXVG, NFILE, fnm), "-nxy"); thanx(stderr); return 0; }
static void rgb_to_ycbcr(img_plane _ycbcr[3],png_bytep *_png){ kiss99_ctx kiss; unsigned char *ydata; unsigned char *cbdata; unsigned char *crdata; int ystride; int cbstride; int crstride; int hstep; int vstep; int w; int h; int i; int j; w=_ycbcr[0].width; h=_ycbcr[0].height; ystride=_ycbcr[0].stride; ydata=_ycbcr[0].data; cbstride=_ycbcr[1].stride; cbdata=_ycbcr[1].data; crstride=_ycbcr[2].stride; crdata=_ycbcr[2].data; hstep=pixel_format&1; vstep=pixel_format&2; kiss99_srand(&kiss,NULL,0); for(j=0;j<h;j+=2){ for(i=0;i<w;i+=2){ int32_t yd[4]; int32_t cbd[4]; int32_t crd[4]; int32_t r0; int32_t g0; int32_t b0; int32_t r1; int32_t g1; int32_t b1; int32_t r2; int32_t g2; int32_t b2; int32_t r3; int32_t g3; int32_t b3; int64_t rsum; int64_t gsum; int64_t bsum; int k; int cb; int cr; /*This often generates more dither values than we use, but keeps them in sync for the luma plane across the different pixel formats.*/ for(k=0;k<4;k++){ /*The size of the dither here is chosen to be the largest divisor of all the corresponding coefficients in the transform that still fits in 31 bits.*/ if (dither) { yd[k]=triangle_rand(&kiss,1223320000); cbd[k]=triangle_rand(&kiss,1479548743); crd[k]=triangle_rand(&kiss,1255654969); } else { yd[k] = 0; cbd[k] = 0; crd[k] = 0; } } get_dithered_pixel(&r0,&g0,&b0,_png[j]+6*i,yd[0],cbd[0],crd[0]); if(i+1<w){ get_dithered_pixel(&r1,&g1,&b1,_png[j]+6*(i+1), yd[1],cbd[hstep],crd[hstep]); } else{ r1=r0; g1=g0; b1=b0; } if(j+1<h){ get_dithered_pixel(&r2,&g2,&b2,_png[j+1]+6*i, yd[2],cbd[vstep],crd[vstep]); if(i+1<w){ get_dithered_pixel(&r3,&g3,&b3,_png[j+1]+6*(i+1), yd[3],cbd[vstep+hstep],crd[vstep+hstep]); } else{ r3=r2; g3=g2; b3=b2; } } else{ r2=r0; g2=g0; b2=b0; r3=r1; g3=g1; b3=b1; } if(pixel_format==PIXEL_FMT_420){ rsum=r0+r1+r2+r3; gsum=g0+g1+g2+g3; bsum=b0+b1+b2+b3; cb=OD_CLAMP255( OD_DIV_ROUND(-29764*rsum-100128*gsum+129892*bsum,304016865)+128); cr=OD_CLAMP255( OD_DIV_ROUND(110236*rsum-100128*gsum-10108*bsum,258011295)+128); cbdata[(j>>1)*cbstride+(i>>1)]=(unsigned char)cb; crdata[(j>>1)*crstride+(i>>1)]=(unsigned char)cr; ydata[j*ystride+i]=calc_y(r0,g0,b0,cb,cr); if(i+1<w)ydata[j*ystride+i+1]=calc_y(r1,g1,b1,cb,cr); if(j+1<h){ ydata[(j+1)*ystride+i]=calc_y(r2,g2,b2,cb,cr); if(i+1<w)ydata[(j+1)*ystride+i+1]=calc_y(r3,g3,b3,cb,cr); } } else if(pixel_format==PIXEL_FMT_422){ rsum=r0+r1; gsum=g0+g1; bsum=b0+b1; cb=OD_CLAMP255( OD_DIV_ROUND(-59528*rsum-200256*gsum+259784*bsum,304016865)+128); cr=OD_CLAMP255( OD_DIV_ROUND(220472*rsum-200256*gsum-20216*bsum,258011295)+128); cbdata[j*cbstride+(i>>1)]=(unsigned char)cb; crdata[j*crstride+(i>>1)]=(unsigned char)cr; ydata[j*ystride+i]=calc_y(r0,g0,b0,cb,cr); if(i+1<w)ydata[j*ystride+i+1]=calc_y(r1,g1,b1,cb,cr); if(j+1<h){ rsum=r2+r3; gsum=g2+g3; bsum=b2+b3; cb=OD_CLAMP255( OD_DIV_ROUND(-59528*rsum-200256*gsum+259784*bsum,304016865)+128); cr=OD_CLAMP255( OD_DIV_ROUND(220472*rsum-200256*gsum-20216*bsum,258011295)+128); cbdata[(j+1)*cbstride+(i>>1)]=(unsigned char)cb; crdata[(j+1)*crstride+(i>>1)]=(unsigned char)cr; ydata[(j+1)*ystride+i]=calc_y(r2,g2,b2,cb,cr); if(i+1<w)ydata[(j+1)*ystride+i+1]=calc_y(r3,g3,b3,cb,cr); }
int gmx_dos(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] computes the Density of States from a simulations.", "In order for this to be meaningful the velocities must be saved", "in the trajecotry with sufficiently high frequency such as to cover", "all vibrations. For flexible systems that would be around a few fs", "between saving. Properties based on the DoS are printed on the", "standard output." "Note that the density of states is calculated from the mass-weighted", "autocorrelation, and by default only from the square of the real", "component rather than absolute value. This means the shape can differ", "substantially from the plain vibrational power spectrum you can", "calculate with gmx velacc." }; const char *bugs[] = { "This program needs a lot of memory: total usage equals the number of atoms times 3 times number of frames times 4 (or 8 when run in double precision)." }; FILE *fp, *fplog; t_topology top; int ePBC = -1; t_trxframe fr; matrix box; int gnx; real t0, t1; t_trxstatus *status; int nV, nframes, n_alloc, i, j, fftcode, Nmol, Natom; double rho, dt, Vsum, V, tmass, dostot, dos2; real **c1, **dos, mi, beta, bfac, *nu, *tt, stddev, c1j; gmx_output_env_t *oenv; gmx_fft_t fft; double cP, DiffCoeff, Delta, f, y, z, sigHS, Shs, Sig, DoS0, recip_fac; double wCdiff, wSdiff, wAdiff, wEdiff; int grpNatoms; int *index; char *grpname; double invNormalize; gmx_bool normalizeAutocorrelation; static gmx_bool bVerbose = TRUE, bAbsolute = FALSE, bNormalizeDos = FALSE; static gmx_bool bRecip = FALSE; static real Temp = 298.15, toler = 1e-6; t_pargs pa[] = { { "-v", FALSE, etBOOL, {&bVerbose}, "Be loud and noisy." }, { "-recip", FALSE, etBOOL, {&bRecip}, "Use cm^-1 on X-axis instead of 1/ps for DoS plots." }, { "-abs", FALSE, etBOOL, {&bAbsolute}, "Use the absolute value of the Fourier transform of the VACF as the Density of States. Default is to use the real component only" }, { "-normdos", FALSE, etBOOL, {&bNormalizeDos}, "Normalize the DoS such that it adds up to 3N. This should usually not be necessary." }, { "-T", FALSE, etREAL, {&Temp}, "Temperature in the simulation" }, { "-toler", FALSE, etREAL, {&toler}, "[HIDDEN]Tolerance when computing the fluidicity using bisection algorithm" } }; t_filenm fnm[] = { { efTRN, "-f", NULL, ffREAD }, { efTPR, "-s", NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, "-vacf", "vacf", ffWRITE }, { efXVG, "-mvacf", "mvacf", ffWRITE }, { efXVG, "-dos", "dos", ffWRITE }, { efLOG, "-g", "dos", ffWRITE }, }; #define NFILE asize(fnm) int npargs; t_pargs *ppa; const char *DoSlegend[] = { "DoS(v)", "DoS(v)[Solid]", "DoS(v)[Diff]" }; npargs = asize(pa); ppa = add_acf_pargs(&npargs, pa); if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME, NFILE, fnm, npargs, ppa, asize(desc), desc, asize(bugs), bugs, &oenv)) { return 0; } beta = 1/(Temp*BOLTZ); fplog = gmx_fio_fopen(ftp2fn(efLOG, NFILE, fnm), "w"); fprintf(fplog, "Doing density of states analysis based on trajectory.\n"); please_cite(fplog, "Pascal2011a"); please_cite(fplog, "Caleman2011b"); read_tps_conf(ftp2fn(efTPR, NFILE, fnm), &top, &ePBC, NULL, NULL, box, TRUE); /* Handle index groups */ get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &grpNatoms, &index, &grpname); V = det(box); tmass = 0; for (i = 0; i < grpNatoms; i++) { tmass += top.atoms.atom[index[i]].m; } Natom = grpNatoms; Nmol = calcMoleculesInIndexGroup(&top.mols, top.atoms.nr, index, grpNatoms); gnx = Natom*DIM; /* Correlation stuff */ snew(c1, gnx); for (i = 0; (i < gnx); i++) { c1[i] = NULL; } read_first_frame(oenv, &status, ftp2fn(efTRN, NFILE, fnm), &fr, TRX_NEED_V); t0 = fr.time; n_alloc = 0; nframes = 0; Vsum = 0; nV = 0; do { if (fr.bBox) { V = det(fr.box); Vsum += V; nV++; } if (nframes >= n_alloc) { n_alloc += 100; for (i = 0; i < gnx; i++) { srenew(c1[i], n_alloc); } } for (i = 0; i < gnx; i += DIM) { c1[i+XX][nframes] = fr.v[index[i/DIM]][XX]; c1[i+YY][nframes] = fr.v[index[i/DIM]][YY]; c1[i+ZZ][nframes] = fr.v[index[i/DIM]][ZZ]; } t1 = fr.time; nframes++; } while (read_next_frame(oenv, status, &fr)); close_trj(status); dt = (t1-t0)/(nframes-1); if (nV > 0) { V = Vsum/nV; } if (bVerbose) { printf("Going to do %d fourier transforms of length %d. Hang on.\n", gnx, nframes); } /* Unfortunately the -normalize program option for the autocorrelation * function calculation is added as a hack with a static variable in the * autocorrelation.c source. That would work if we called the normal * do_autocorr(), but this routine overrides that by directly calling * the low-level functionality. That unfortunately leads to ignoring the * default value for the option (which is to normalize). * Since the absolute value seems to be important for the subsequent * analysis below, we detect the value directly from the option, calculate * the autocorrelation without normalization, and then apply the * normalization just to the autocorrelation output * (or not, if the user asked for a non-normalized autocorrelation). */ normalizeAutocorrelation = opt2parg_bool("-normalize", npargs, ppa); /* Note that we always disable normalization here, regardless of user settings */ low_do_autocorr(NULL, oenv, NULL, nframes, gnx, nframes, c1, dt, eacNormal, 0, FALSE, FALSE, FALSE, -1, -1, 0); snew(dos, DOS_NR); for (j = 0; (j < DOS_NR); j++) { snew(dos[j], nframes+4); } if (bVerbose) { printf("Going to merge the ACFs into the mass-weighted and plain ACF\n"); } for (i = 0; (i < gnx); i += DIM) { mi = top.atoms.atom[index[i/DIM]].m; for (j = 0; (j < nframes/2); j++) { c1j = (c1[i+XX][j] + c1[i+YY][j] + c1[i+ZZ][j]); dos[VACF][j] += c1j/Natom; dos[MVACF][j] += mi*c1j; } } fp = xvgropen(opt2fn("-vacf", NFILE, fnm), "Velocity autocorrelation function", "Time (ps)", "C(t)", oenv); snew(tt, nframes/2); invNormalize = normalizeAutocorrelation ? 1.0/dos[VACF][0] : 1.0; for (j = 0; (j < nframes/2); j++) { tt[j] = j*dt; fprintf(fp, "%10g %10g\n", tt[j], dos[VACF][j] * invNormalize); } xvgrclose(fp); fp = xvgropen(opt2fn("-mvacf", NFILE, fnm), "Mass-weighted velocity autocorrelation function", "Time (ps)", "C(t)", oenv); invNormalize = normalizeAutocorrelation ? 1.0/dos[VACF][0] : 1.0; for (j = 0; (j < nframes/2); j++) { fprintf(fp, "%10g %10g\n", tt[j], dos[MVACF][j] * invNormalize); } xvgrclose(fp); if ((fftcode = gmx_fft_init_1d_real(&fft, nframes/2, GMX_FFT_FLAG_NONE)) != 0) { gmx_fatal(FARGS, "gmx_fft_init_1d_real returned %d", fftcode); } if ((fftcode = gmx_fft_1d_real(fft, GMX_FFT_REAL_TO_COMPLEX, (void *)dos[MVACF], (void *)dos[DOS])) != 0) { gmx_fatal(FARGS, "gmx_fft_1d_real returned %d", fftcode); } /* First compute the DoS */ /* Magic factor of 8 included now. */ bfac = 8*dt*beta/2; dos2 = 0; snew(nu, nframes/4); for (j = 0; (j < nframes/4); j++) { nu[j] = 2*j/(t1-t0); dos2 += gmx::square(dos[DOS][2*j]) + gmx::square(dos[DOS][2*j+1]); if (bAbsolute) { dos[DOS][j] = bfac*std::hypot(dos[DOS][2*j], dos[DOS][2*j+1]); } else { dos[DOS][j] = bfac*dos[DOS][2*j]; } } /* Normalize it */ dostot = evaluate_integral(nframes/4, nu, dos[DOS], NULL, nframes/4, &stddev); if (bNormalizeDos) { for (j = 0; (j < nframes/4); j++) { dos[DOS][j] *= 3*Natom/dostot; } } /* Now analyze it */ DoS0 = dos[DOS][0]; /* Note this eqn. is incorrect in Pascal2011a! */ Delta = ((2*DoS0/(9*Natom))*std::sqrt(M_PI*BOLTZ*Temp*Natom/tmass)* std::pow((Natom/V), 1.0/3.0)*std::pow(6.0/M_PI, 2.0/3.0)); f = calc_fluidicity(Delta, toler); y = calc_y(f, Delta, toler); z = calc_compress(y); Sig = BOLTZ*(5.0/2.0+std::log(2*M_PI*BOLTZ*Temp/(gmx::square(PLANCK))*V/(f*Natom))); Shs = Sig+calc_Shs(f, y); rho = (tmass*AMU)/(V*NANO*NANO*NANO); sigHS = std::cbrt(6*y*V/(M_PI*Natom)); fprintf(fplog, "System = \"%s\"\n", *top.name); fprintf(fplog, "Nmol = %d\n", Nmol); fprintf(fplog, "Natom = %d\n", Natom); fprintf(fplog, "dt = %g ps\n", dt); fprintf(fplog, "tmass = %g amu\n", tmass); fprintf(fplog, "V = %g nm^3\n", V); fprintf(fplog, "rho = %g g/l\n", rho); fprintf(fplog, "T = %g K\n", Temp); fprintf(fplog, "beta = %g mol/kJ\n", beta); fprintf(fplog, "\nDoS parameters\n"); fprintf(fplog, "Delta = %g\n", Delta); fprintf(fplog, "fluidicity = %g\n", f); fprintf(fplog, "hard sphere packing fraction = %g\n", y); fprintf(fplog, "hard sphere compressibility = %g\n", z); fprintf(fplog, "ideal gas entropy = %g\n", Sig); fprintf(fplog, "hard sphere entropy = %g\n", Shs); fprintf(fplog, "sigma_HS = %g nm\n", sigHS); fprintf(fplog, "DoS0 = %g\n", DoS0); fprintf(fplog, "Dos2 = %g\n", dos2); fprintf(fplog, "DoSTot = %g\n", dostot); /* Now compute solid (2) and diffusive (3) components */ fp = xvgropen(opt2fn("-dos", NFILE, fnm), "Density of states", bRecip ? "E (cm\\S-1\\N)" : "\\f{12}n\\f{4} (1/ps)", "\\f{4}S(\\f{12}n\\f{4})", oenv); xvgr_legend(fp, asize(DoSlegend), DoSlegend, oenv); recip_fac = bRecip ? (1e7/SPEED_OF_LIGHT) : 1.0; for (j = 0; (j < nframes/4); j++) { dos[DOS_DIFF][j] = DoS0/(1+gmx::square(DoS0*M_PI*nu[j]/(6*f*Natom))); dos[DOS_SOLID][j] = dos[DOS][j]-dos[DOS_DIFF][j]; fprintf(fp, "%10g %10g %10g %10g\n", recip_fac*nu[j], dos[DOS][j]/recip_fac, dos[DOS_SOLID][j]/recip_fac, dos[DOS_DIFF][j]/recip_fac); } xvgrclose(fp); /* Finally analyze the results! */ wCdiff = 0.5; wSdiff = Shs/(3*BOLTZ); /* Is this correct? */ wEdiff = 0.5; wAdiff = wEdiff-wSdiff; for (j = 0; (j < nframes/4); j++) { dos[DOS_CP][j] = (dos[DOS_DIFF][j]*wCdiff + dos[DOS_SOLID][j]*wCsolid(nu[j], beta)); dos[DOS_S][j] = (dos[DOS_DIFF][j]*wSdiff + dos[DOS_SOLID][j]*wSsolid(nu[j], beta)); dos[DOS_A][j] = (dos[DOS_DIFF][j]*wAdiff + dos[DOS_SOLID][j]*wAsolid(nu[j], beta)); dos[DOS_E][j] = (dos[DOS_DIFF][j]*wEdiff + dos[DOS_SOLID][j]*wEsolid(nu[j], beta)); } DiffCoeff = evaluate_integral(nframes/2, tt, dos[VACF], NULL, nframes/2, &stddev); DiffCoeff = 1000*DiffCoeff/3.0; fprintf(fplog, "Diffusion coefficient from VACF %g 10^-5 cm^2/s\n", DiffCoeff); fprintf(fplog, "Diffusion coefficient from DoS %g 10^-5 cm^2/s\n", 1000*DoS0/(12*tmass*beta)); cP = BOLTZ * evaluate_integral(nframes/4, nu, dos[DOS_CP], NULL, nframes/4, &stddev); fprintf(fplog, "Heat capacity %g J/mol K\n", 1000*cP/Nmol); fprintf(fplog, "\nArrivederci!\n"); gmx_fio_fclose(fplog); do_view(oenv, ftp2fn(efXVG, NFILE, fnm), "-nxy"); return 0; }
double calc_theta(int n){ return asin(calc_y(n) * n - 1.0); }
double rectangle(int n){ double y = calc_y(n); return y * y * n / 2.0; }