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; }
static void calc_tetra_order_interface(const char *fnNDX, const char *fnTPS, const char *fnTRX, real binw, int tblock, int *nframes, int *nslicex, int *nslicey, real sgang1, real sgang2, real ****intfpos, output_env_t oenv) { FILE *fpsg = NULL, *fpsk = NULL; char *sgslfn = "sg_ang_mesh"; /* Hardcoded filenames for debugging*/ char *skslfn = "sk_dist_mesh"; t_topology top; int ePBC; char title[STRLEN], subtitle[STRLEN]; t_trxstatus *status; int natoms; real t; rvec *xtop, *x; matrix box; real sg, sk, sgintf, pos; atom_id **index = NULL; char **grpname = NULL; int i, j, k, n, *isize, ng, nslicez, framenr; real ***sg_grid = NULL, ***sk_grid = NULL, ***sg_fravg = NULL, ***sk_fravg = NULL, ****sk_4d = NULL, ****sg_4d = NULL; int *perm; int ndx1, ndx2; int bins; const real onehalf = 1.0/2.0; /* real ***intfpos[2]; pointers to arrays of two interface positions zcoord(framenr,xbin,ybin): intfpos[interface_index][t][nslicey*x+y] * i.e 1D Row-major order in (t,x,y) */ read_tps_conf(fnTPS, title, &top, &ePBC, &xtop, NULL, box, FALSE); *nslicex = (int)(box[XX][XX]/binw + onehalf); /*Calculate slicenr from binwidth*/ *nslicey = (int)(box[YY][YY]/binw + onehalf); nslicez = (int)(box[ZZ][ZZ]/binw + onehalf); ng = 1; /* get index groups */ printf("Select the group that contains the atoms you want to use for the tetrahedrality order parameter calculation:\n"); snew(grpname, ng); snew(index, ng); snew(isize, ng); get_index(&top.atoms, fnNDX, ng, isize, index, grpname); /* Analyze trajectory */ natoms = read_first_x(oenv, &status, fnTRX, &t, &x, box); if (natoms > top.atoms.nr) { gmx_fatal(FARGS, "Topology (%d atoms) does not match trajectory (%d atoms)", top.atoms.nr, natoms); } check_index(NULL, ng, index[0], NULL, natoms); /*Prepare structures for temporary storage of frame info*/ snew(sg_grid, *nslicex); snew(sk_grid, *nslicex); for (i = 0; i < *nslicex; i++) { snew(sg_grid[i], *nslicey); snew(sk_grid[i], *nslicey); for (j = 0; j < *nslicey; j++) { snew(sg_grid[i][j], nslicez); snew(sk_grid[i][j], nslicez); } } sg_4d = NULL; sk_4d = NULL; *nframes = 0; framenr = 0; /* Loop over frames*/ do { /*Initialize box meshes (temporary storage for each tblock frame -reinitialise every tblock steps */ if (framenr%tblock == 0) { srenew(sk_4d, *nframes+1); srenew(sg_4d, *nframes+1); snew(sg_fravg, *nslicex); snew(sk_fravg, *nslicex); for (i = 0; i < *nslicex; i++) { snew(sg_fravg[i], *nslicey); snew(sk_fravg[i], *nslicey); for (j = 0; j < *nslicey; j++) { snew(sg_fravg[i][j], nslicez); snew(sk_fravg[i][j], nslicez); } } } find_tetra_order_grid(top, ePBC, natoms, box, x, isize[0], index[0], t, &sg, &sk, *nslicex, *nslicey, nslicez, sg_grid, sk_grid); for (i = 0; i < *nslicex; i++) { for (j = 0; j < *nslicey; j++) { for (k = 0; k < nslicez; k++) { sk_fravg[i][j][k] += sk_grid[i][j][k]/tblock; sg_fravg[i][j][k] += sg_grid[i][j][k]/tblock; } } } framenr++; if (framenr%tblock == 0) { sk_4d[*nframes] = sk_fravg; sg_4d[*nframes] = sg_fravg; (*nframes)++; } } while (read_next_x(oenv, status, &t, natoms, x, box)); close_trj(status); sfree(grpname); sfree(index); sfree(isize); /*Debugging for printing out the entire order parameter meshes.*/ if (debug) { fpsg = xvgropen(sgslfn, "S\\sg\\N Angle Order Parameter / Meshpoint", "(nm)", "S\\sg\\N", oenv); fpsk = xvgropen(skslfn, "S\\sk\\N Distance Order Parameter / Meshpoint", "(nm)", "S\\sk\\N", oenv); for (n = 0; n < (*nframes); n++) { fprintf(fpsg, "%i\n", n); fprintf(fpsk, "%i\n", n); for (i = 0; (i < *nslicex); i++) { for (j = 0; j < *nslicey; j++) { for (k = 0; k < nslicez; k++) { fprintf(fpsg, "%4f %4f %4f %8f\n", (i+0.5)*box[XX][XX]/(*nslicex), (j+0.5)*box[YY][YY]/(*nslicey), (k+0.5)*box[ZZ][ZZ]/nslicez, sg_4d[n][i][j][k]); fprintf(fpsk, "%4f %4f %4f %8f\n", (i+0.5)*box[XX][XX]/(*nslicex), (j+0.5)*box[YY][YY]/(*nslicey), (k+0.5)*box[ZZ][ZZ]/nslicez, sk_4d[n][i][j][k]); } } } } xvgrclose(fpsg); xvgrclose(fpsk); } /* Find positions of interface z by scanning orderparam for each frame and for each xy-mesh cylinder along z*/ /*Simple trial: assume interface is in the middle of -sgang1 and sgang2*/ sgintf = 0.5*(sgang1+sgang2); /*Allocate memory for interface arrays; */ snew((*intfpos), 2); snew((*intfpos)[0], *nframes); snew((*intfpos)[1], *nframes); bins = (*nslicex)*(*nslicey); snew(perm, nslicez); /*permutation array for sorting along normal coordinate*/ for (n = 0; n < *nframes; n++) { snew((*intfpos)[0][n], bins); snew((*intfpos)[1][n], bins); for (i = 0; i < *nslicex; i++) { for (j = 0; j < *nslicey; j++) { rangeArray(perm, nslicez); /*reset permutation array to identity*/ /*Binsearch returns 2 bin-numbers where the order param is <= setpoint sgintf*/ ndx1 = start_binsearch(sg_4d[n][i][j], perm, 0, nslicez/2-1, sgintf, 1); ndx2 = start_binsearch(sg_4d[n][i][j], perm, nslicez/2, nslicez-1, sgintf, -1); /*Use linear interpolation to smooth out the interface position*/ /*left interface (0)*/ /*if((sg_4d[n][i][j][perm[ndx1+1]]-sg_4d[n][i][j][perm[ndx1]])/sg_4d[n][i][j][perm[ndx1]] > 0.01){ pos=( (sgintf-sg_4d[n][i][j][perm[ndx1]])*perm[ndx1+1]+(sg_4d[n][i][j][perm[ndx1+1]]-sgintf)*perm[ndx1 ])*/ (*intfpos)[0][n][j+*nslicey*i] = (perm[ndx1]+onehalf)*binw; /*right interface (1)*/ /*alpha=(sgintf-sg_4d[n][i][j][perm[ndx2]])/(sg_4d[n][i][j][perm[ndx2]+1]-sg_4d[n][i][j][perm[ndx2]]);*/ /*(*intfpos)[1][n][j+*nslicey*i]=((1-alpha)*perm[ndx2]+alpha*(perm[ndx2]+1)+onehalf)*box[ZZ][ZZ]/nslicez;*/ (*intfpos)[1][n][j+*nslicey*i] = (perm[ndx2]+onehalf)*binw; } } } /*sfree(perm);*/ sfree(sk_4d); sfree(sg_4d); /*sfree(sg_grid);*/ /*sfree(sk_grid);*/ }