1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
2 * $Id: densorder.c,v 0.9
4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-2001
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
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 * Do check out http://www.gromacs.org , or mail us at gromacs@gromacs.org .
34 * Gyas ROwers Mature At Cryogenic Speed
60 #include "binsearch.h"
61 #include "powerspect.h"
63 /* Print name of first atom in all groups in index file */
64 static void print_types(atom_id index
[], atom_id a
[], int ngrps
,
65 char *groups
[], t_topology
*top
)
69 fprintf(stderr
,"Using following groups: \n");
70 for(i
= 0; i
< ngrps
; i
++)
71 fprintf(stderr
,"Groupname: %s First atomname: %s First atomnr %u\n",
72 groups
[i
], *(top
->atoms
.atomname
[a
[index
[i
]]]), a
[index
[i
]]);
76 static void check_length(real length
, int a
, int b
)
79 fprintf(stderr
,"WARNING: distance between atoms %d and "
80 "%d > 0.3 nm (%f). Index file might be corrupt.\n",
84 static void find_tetra_order_grid(t_topology top
, int ePBC
,
85 int natoms
, matrix box
,
86 rvec x
[],int maxidx
,atom_id index
[],
87 real time
, real
*sgmean
, real
*skmean
,
88 int nslicex
, int nslicey
, int nslicez
,
89 real
***sggrid
,real
***skgrid
)
91 int ix
,jx
,i
,j
,k
,l
,n
,*nn
[4];
92 rvec dx
,rj
,rk
,urk
,urj
;
93 real cost
,cost2
,*sgmol
,*skmol
,rmean
,rmean2
,r2
,box2
,*r_nn
[4];
95 int slindex_x
,slindex_y
,slindex_z
;
97 real onethird
=1.0/3.0;
100 /* dmat = init_mat(maxidx, FALSE); */
102 box2
= box
[XX
][XX
] * box
[XX
][XX
];
104 /* Initialize expanded sl_count array */
105 snew(sl_count
,nslicex
);
106 for(i
=0;i
<nslicex
;i
++)
108 snew(sl_count
[i
],nslicey
);
109 for(j
=0;j
<nslicey
;j
++)
111 snew(sl_count
[i
][j
],nslicez
);
116 for (i
=0; (i
<4); i
++)
118 snew(r_nn
[i
],natoms
);
121 for (j
=0; (j
<natoms
); j
++)
130 /* Must init pbc every step because of pressure coupling */
131 gpbc
= gmx_rmpbc_init(&top
.idef
,ePBC
,natoms
,box
);
132 gmx_rmpbc(gpbc
,natoms
,box
,x
);
137 for (i
=0; (i
<maxidx
); i
++)
138 { /* loop over index file */
140 for (j
=0; (j
<maxidx
); j
++)
143 if (i
== j
) continue;
147 pbc_dx(&pbc
,x
[ix
],x
[jx
],dx
);
150 /* set_mat_entry(dmat,i,j,r2); */
152 /* determine the nearest neighbours */
155 r_nn
[3][i
] = r_nn
[2][i
]; nn
[3][i
] = nn
[2][i
];
156 r_nn
[2][i
] = r_nn
[1][i
]; nn
[2][i
] = nn
[1][i
];
157 r_nn
[1][i
] = r_nn
[0][i
]; nn
[1][i
] = nn
[0][i
];
158 r_nn
[0][i
] = r2
; nn
[0][i
] = j
;
159 } else if (r2
< r_nn
[1][i
])
161 r_nn
[3][i
] = r_nn
[2][i
]; nn
[3][i
] = nn
[2][i
];
162 r_nn
[2][i
] = r_nn
[1][i
]; nn
[2][i
] = nn
[1][i
];
163 r_nn
[1][i
] = r2
; nn
[1][i
] = j
;
164 } else if (r2
< r_nn
[2][i
])
166 r_nn
[3][i
] = r_nn
[2][i
]; nn
[3][i
] = nn
[2][i
];
167 r_nn
[2][i
] = r2
; nn
[2][i
] = j
;
168 } else if (r2
< r_nn
[3][i
])
170 r_nn
[3][i
] = r2
; nn
[3][i
] = j
;
175 /* calculate mean distance between nearest neighbours */
177 for (j
=0; (j
<4); j
++)
179 r_nn
[j
][i
] = sqrt(r_nn
[j
][i
]);
188 /* Chau1998a eqn 3 */
189 /* angular part tetrahedrality order parameter per atom */
190 for (j
=0; (j
<3); j
++)
192 for (k
=j
+1; (k
<4); k
++)
194 pbc_dx(&pbc
,x
[ix
],x
[index
[nn
[k
][i
]]],rk
);
195 pbc_dx(&pbc
,x
[ix
],x
[index
[nn
[j
][i
]]],rj
);
200 cost
= iprod(urk
,urj
) + onethird
;
208 /* normalize sgmol between 0.0 and 1.0 */
209 sgmol
[i
] = 3*sgmol
[i
]/32;
212 /* distance part tetrahedrality order parameter per atom */
213 rmean2
= 4 * 3 * rmean
* rmean
;
214 for (j
=0; (j
<4); j
++)
216 skmol
[i
] += (rmean
- r_nn
[j
][i
]) * (rmean
- r_nn
[j
][i
]) / rmean2
;
217 /* printf("%d %f (%f %f %f %f) \n",
218 i, skmol[i], rmean, rmean2, r_nn[j][i], (rmean - r_nn[j][i]) );
224 /* Compute sliced stuff in x y z*/
225 slindex_x
= gmx_nint((1+x
[i
][XX
]/box
[XX
][XX
])*nslicex
) % nslicex
;
226 slindex_y
= gmx_nint((1+x
[i
][YY
]/box
[YY
][YY
])*nslicey
) % nslicey
;
227 slindex_z
= gmx_nint((1+x
[i
][ZZ
]/box
[ZZ
][ZZ
])*nslicez
) % nslicez
;
228 sggrid
[slindex_x
][slindex_y
][slindex_z
] += sgmol
[i
];
229 skgrid
[slindex_x
][slindex_y
][slindex_z
] += skmol
[i
];
230 (sl_count
[slindex_x
][slindex_y
][slindex_z
])++;
231 } /* loop over entries in index file */
236 for(i
=0; (i
<nslicex
); i
++)
238 for(j
=0; j
<nslicey
; j
++)
240 for(k
=0;k
<nslicez
;k
++)
242 if (sl_count
[i
][j
][k
] > 0)
244 sggrid
[i
][j
][k
] /= sl_count
[i
][j
][k
];
245 skgrid
[i
][j
][k
] /= sl_count
[i
][j
][k
];
254 for (i
=0; (i
<4); i
++)
261 /*Determines interface from tetrahedral order parameter in box with specified binwidth. */
262 /*Outputs interface positions(bins), the number of timeframes, and the number of surface-mesh points in xy*/
264 static void calc_tetra_order_interface(const char *fnNDX
,const char *fnTPS
,const char *fnTRX
, real binw
, int tblock
,
265 int *nframes
, int *nslicex
, int *nslicey
,
266 real sgang1
,real sgang2
,real
****intfpos
,
269 FILE *fpsg
=NULL
,*fpsk
=NULL
;
270 char *sgslfn
="sg_ang_mesh"; /* Hardcoded filenames for debugging*/
271 char *skslfn
="sk_dist_mesh";
274 char title
[STRLEN
],subtitle
[STRLEN
];
280 real sg
,sk
, sgintf
, pos
;
281 atom_id
**index
=NULL
;
283 int i
,j
,k
,n
,*isize
,ng
, nslicez
, framenr
;
284 real
***sg_grid
=NULL
,***sk_grid
=NULL
, ***sg_fravg
=NULL
, ***sk_fravg
=NULL
, ****sk_4d
=NULL
, ****sg_4d
=NULL
;
288 const real onehalf
=1.0/2.0;
289 /* real ***intfpos[2]; pointers to arrays of two interface positions zcoord(framenr,xbin,ybin): intfpos[interface_index][t][nslicey*x+y]
290 * i.e 1D Row-major order in (t,x,y) */
293 read_tps_conf(fnTPS
,title
,&top
,&ePBC
,&xtop
,NULL
,box
,FALSE
);
295 *nslicex
= (int)(box
[XX
][XX
]/binw
+ onehalf
); /*Calculate slicenr from binwidth*/
296 *nslicey
= (int)(box
[YY
][YY
]/binw
+ onehalf
);
297 nslicez
= (int)(box
[ZZ
][ZZ
]/binw
+ onehalf
);
302 /* get index groups */
303 printf("Select the group that contains the atoms you want to use for the tetrahedrality order parameter calculation:\n");
307 get_index(&top
.atoms
,fnNDX
,ng
,isize
,index
,grpname
);
309 /* Analyze trajectory */
310 natoms
=read_first_x(oenv
,&status
,fnTRX
,&t
,&x
,box
);
311 if ( natoms
> top
.atoms
.nr
)
312 gmx_fatal(FARGS
,"Topology (%d atoms) does not match trajectory (%d atoms)",
313 top
.atoms
.nr
,natoms
);
314 check_index(NULL
,ng
,index
[0],NULL
,natoms
);
317 /*Prepare structures for temporary storage of frame info*/
318 snew(sg_grid
,*nslicex
);
319 snew(sk_grid
,*nslicex
);
320 for(i
=0;i
<*nslicex
;i
++)
322 snew(sg_grid
[i
],*nslicey
);
323 snew(sk_grid
[i
],*nslicey
);
324 for(j
=0;j
<*nslicey
;j
++)
326 snew(sg_grid
[i
][j
],nslicez
);
327 snew(sk_grid
[i
][j
],nslicez
);
336 /* Loop over frames*/
339 /*Initialize box meshes (temporary storage for each tblock frame -reinitialise every tblock steps */
340 if(framenr
%tblock
==0)
342 srenew(sk_4d
,*nframes
+1);
343 srenew(sg_4d
,*nframes
+1);
344 snew(sg_fravg
,*nslicex
);
345 snew(sk_fravg
,*nslicex
);
346 for(i
=0;i
<*nslicex
;i
++)
348 snew(sg_fravg
[i
],*nslicey
);
349 snew(sk_fravg
[i
],*nslicey
);
350 for(j
=0;j
<*nslicey
;j
++)
352 snew(sg_fravg
[i
][j
],nslicez
);
353 snew(sk_fravg
[i
][j
],nslicez
);
358 find_tetra_order_grid(top
,ePBC
,natoms
,box
,x
,isize
[0],index
[0],t
,
359 &sg
,&sk
,*nslicex
,*nslicey
,nslicez
,sg_grid
,sk_grid
);
360 for(i
=0;i
<*nslicex
;i
++)
362 for(j
=0;j
<*nslicey
;j
++)
364 for(k
=0;k
<nslicez
;k
++)
366 sk_fravg
[i
][j
][k
]+=sk_grid
[i
][j
][k
]/tblock
;
367 sg_fravg
[i
][j
][k
]+=sg_grid
[i
][j
][k
]/tblock
;
374 if(framenr
%tblock
== 0)
376 sk_4d
[*nframes
] = sk_fravg
;
377 sg_4d
[*nframes
] = sg_fravg
;
381 } while (read_next_x(oenv
,status
,&t
,natoms
,x
,box
));
388 /*Debugging for printing out the entire order parameter meshes.*/
391 fpsg
= xvgropen(sgslfn
,"S\\sg\\N Angle Order Parameter / Meshpoint","(nm)","S\\sg\\N",oenv
);
392 fpsk
= xvgropen(skslfn
,"S\\sk\\N Distance Order Parameter / Meshpoint","(nm)","S\\sk\\N",oenv
);
393 for(n
=0;n
<(*nframes
);n
++)
395 fprintf(fpsg
,"%i\n",n
);
396 fprintf(fpsk
,"%i\n",n
);
397 for(i
=0; (i
<*nslicex
); i
++)
399 for(j
=0;j
<*nslicey
;j
++)
401 for(k
=0;k
<nslicez
;k
++)
403 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
]);
404 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
]);
414 /* Find positions of interface z by scanning orderparam for each frame and for each xy-mesh cylinder along z*/
416 /*Simple trial: assume interface is in the middle of -sgang1 and sgang2*/
417 sgintf
=0.5*(sgang1
+sgang2
);
420 /*Allocate memory for interface arrays; */
422 snew((*intfpos
)[0],*nframes
);
423 snew((*intfpos
)[1],*nframes
);
425 bins
=(*nslicex
)*(*nslicey
);
428 snew(perm
,nslicez
); /*permutation array for sorting along normal coordinate*/
431 for (n
=0;n
<*nframes
;n
++)
433 snew((*intfpos
)[0][n
],bins
);
434 snew((*intfpos
)[1][n
],bins
);
435 for(i
=0;i
<*nslicex
;i
++)
437 for(j
=0;j
<*nslicey
;j
++)
439 rangeArray(perm
,nslicez
); /*reset permutation array to identity*/
440 /*Binsearch returns 2 bin-numbers where the order param is <= setpoint sgintf*/
441 ndx1
=start_binsearch(sg_4d
[n
][i
][j
],perm
,0,nslicez
/2-1,sgintf
,1);
442 ndx2
=start_binsearch(sg_4d
[n
][i
][j
],perm
,nslicez
/2,nslicez
-1,sgintf
,-1);
443 /*Use linear interpolation to smooth out the interface position*/
445 /*left interface (0)*/
446 /*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){
447 pos=( (sgintf-sg_4d[n][i][j][perm[ndx1]])*perm[ndx1+1]+(sg_4d[n][i][j][perm[ndx1+1]]-sgintf)*perm[ndx1 ])*/
448 (*intfpos
)[0][n
][j
+*nslicey
*i
]=(perm
[ndx1
]+onehalf
)*binw
;
449 /*right interface (1)*/
450 /*alpha=(sgintf-sg_4d[n][i][j][perm[ndx2]])/(sg_4d[n][i][j][perm[ndx2]+1]-sg_4d[n][i][j][perm[ndx2]]);*/
451 /*(*intfpos)[1][n][j+*nslicey*i]=((1-alpha)*perm[ndx2]+alpha*(perm[ndx2]+1)+onehalf)*box[ZZ][ZZ]/nslicez;*/
452 (*intfpos
)[1][n
][j
+*nslicey
*i
]=(perm
[ndx2
]+onehalf
)*binw
;
467 static void writesurftoxpms(real
***surf
, int tblocks
,int xbins
, int ybins
, real bw
,char **outfiles
,int maplevels
)
472 real
**profile1
, **profile2
;
473 real max1
, max2
, min1
, min2
, *xticks
, *yticks
;
476 FILE *xpmfile1
, *xpmfile2
;
478 /*Prepare xpm structures for output*/
480 /*Allocate memory to tick's and matrices*/
481 snew (xticks
,xbins
+1);
482 snew (yticks
,ybins
+1);
484 profile1
=mk_matrix(xbins
,ybins
,FALSE
);
485 profile2
=mk_matrix(xbins
,ybins
,FALSE
);
487 for (i
=0;i
<xbins
+1;i
++) xticks
[i
]+=bw
;
488 for (j
=0;j
<ybins
+1;j
++) yticks
[j
]+=bw
;
490 xpmfile1
= ffopen(outfiles
[0],"w");
491 xpmfile2
= ffopen(outfiles
[1],"w");
496 for(n
=0;n
<tblocks
;n
++)
498 sprintf(numbuf
,"%5d",n
);
499 /*Filling matrices for inclusion in xpm-files*/
504 profile1
[i
][j
]=(surf
[0][n
][j
+ybins
*i
]);
505 profile2
[i
][j
]=(surf
[1][n
][j
+ybins
*i
]);
506 /*Finding max and min values*/
507 if(profile1
[i
][j
]>max1
) max1
=profile1
[i
][j
];
508 if(profile1
[i
][j
]<min1
) min1
=profile1
[i
][j
];
509 if(profile2
[i
][j
]>max2
) max2
=profile2
[i
][j
];
510 if(profile2
[i
][j
]<min2
) min2
=profile2
[i
][j
];
514 write_xpm(xpmfile1
,3,numbuf
,"Height","x[nm]","y[nm]",xbins
,ybins
,xticks
,yticks
,profile1
,min1
,max1
,lo
,hi
,&maplevels
);
515 write_xpm(xpmfile2
,3,numbuf
,"Height","x[nm]","y[nm]",xbins
,ybins
,xticks
,yticks
,profile2
,min2
,max2
,lo
,hi
,&maplevels
);
530 static void writeraw(real
***surf
, int tblocks
,int xbins
, int ybins
,char **fnms
){
534 raw1
=ffopen(fnms
[0],"w");
535 raw2
=ffopen(fnms
[1],"w");
536 fprintf(raw1
,"#Legend\n#TBlock\n#Xbin Ybin Z t\n");
537 fprintf(raw2
,"#Legend\n#TBlock\n#Xbin Ybin Z t\n");
538 for (n
=0;n
<tblocks
;n
++)
540 fprintf(raw1
,"%5d\n",n
);
541 fprintf(raw2
,"%5d\n",n
);
546 fprintf(raw1
,"%i %i %8.5f\n",i
,j
,(surf
[0][n
][j
+ybins
*i
]));
547 fprintf(raw2
,"%i %i %8.5f\n",i
,j
,(surf
[1][n
][j
+ybins
*i
]));
558 int gmx_hydorder(int argc
,char *argv
[])
560 static const char *desc
[] = {
561 "g_hydorder computes the tetrahedrality order parameters around a ",
562 "given atom. Both angle an distance order parameters are calculated. See",
563 "P.-L. Chau and A.J. Hardwick, Mol. Phys., 93, (1998), 511-518.",
564 "for more details.[BR]"
565 "This application calculates the orderparameter in a 3d-mesh in the box, and",
566 "with 2 phases in the box gives the user the option to define a 2D interface in time",
567 "separating the faces by specifying parameters -sgang1 and -sgang2 (It is important",
568 "to select these judiciously)"};
571 static int nsttblock
=1;
572 static int nlevels
=100;
573 static real binwidth
= 1.0; /* binwidth in mesh */
575 static real sg2
= 1; /* order parameters for bulk phases */
576 static gmx_bool bFourier
= FALSE
;
577 static gmx_bool bRawOut
= FALSE
;
578 int frames
,xslices
,yslices
; /* Dimensions of interface arrays*/
579 real
***intfpos
; /* Interface arrays (intfnr,t,xy) -potentially large */
580 static char *normal_axis
[] = { NULL
, "z", "x", "y", NULL
};
583 { "-d", FALSE
, etENUM
, {normal_axis
},
584 "Direction of the normal on the membrane" },
585 { "-bw", FALSE
, etREAL
, {&binwidth
},
586 "Binwidth of box mesh" },
587 { "-sgang1",FALSE
,etREAL
, {&sg1
},
588 "tetrahedral angle parameter in Phase 1 (bulk)" },
589 { "-sgang2",FALSE
,etREAL
, {&sg2
},
590 "tetrahedral angle parameter in Phase 2 (bulk)" },
591 { "-tblock",FALSE
,etINT
,{&nsttblock
},
592 "Number of frames in one time-block average"},
593 { "-nlevel", FALSE
,etINT
, {&nlevels
},
594 "Number of Height levels in 2D - XPixMaps"}
597 t_filenm fnm
[] = { /* files for g_order */
598 { efTRX
, "-f", NULL
, ffREAD
}, /* trajectory file */
599 { efNDX
, "-n", NULL
, ffREAD
}, /* index file */
600 { efTPX
, "-s", NULL
, ffREAD
}, /* topology file */
601 { efXPM
, "-o", "intf", ffWRMULT
}, /* XPM- surface maps */
602 { efOUT
,"-or","raw", ffOPTWRMULT
}, /* xvgr output file */
603 { efOUT
,"-Spect","intfspect",ffOPTWRMULT
}, /* Fourier spectrum interfaces */
605 #define NFILE asize(fnm)
608 const char *ndxfnm
,*tpsfnm
,*trxfnm
;
609 char **spectra
,**intfn
, **raw
;
610 int nfspect
,nfxpm
, nfraw
;
613 CopyRight(stderr
,argv
[0]);
615 parse_common_args(&argc
,argv
,PCA_CAN_VIEW
| PCA_CAN_TIME
| PCA_BE_NICE
,
616 NFILE
,fnm
,asize(pa
),pa
,asize(desc
),desc
,0,NULL
,&oenv
);
617 bFourier
= opt2bSet("-Spect",NFILE
,fnm
);
618 bRawOut
= opt2bSet("-or",NFILE
,fnm
);
621 gmx_fatal(FARGS
,"Can not have binwidth < 0");
623 ndxfnm
= ftp2fn(efNDX
,NFILE
,fnm
);
624 tpsfnm
= ftp2fn(efTPX
,NFILE
,fnm
);
625 trxfnm
= ftp2fn(efTRX
,NFILE
,fnm
);
628 if (strcmp(normal_axis
[0],"x") == 0) axis
= XX
;
629 else if (strcmp(normal_axis
[0],"y") == 0) axis
= YY
;
630 else if (strcmp(normal_axis
[0],"z") == 0) axis
= ZZ
;
631 else gmx_fatal(FARGS
,"Invalid axis, use x, y or z");
635 fprintf(stderr
,"Taking x axis as normal to the membrane\n");
638 fprintf(stderr
,"Taking y axis as normal to the membrane\n");
641 fprintf(stderr
,"Taking z axis as normal to the membrane\n");
645 /* tetraheder order parameter */
646 /* If either of the options is set we compute both */
647 nfxpm
=opt2fns(&intfn
,"-o",NFILE
,fnm
);
650 gmx_fatal(FARGS
,"No or not correct number (2) of output-files: %d",nfxpm
);
652 calc_tetra_order_interface(ndxfnm
,tpsfnm
,trxfnm
,binwidth
,nsttblock
,&frames
,&xslices
,&yslices
,sg1
,sg2
,&intfpos
,oenv
);
653 writesurftoxpms(intfpos
,frames
,xslices
,yslices
,binwidth
,intfn
,nlevels
);
657 nfspect
=opt2fns(&spectra
,"-Spect",NFILE
,fnm
);
660 gmx_fatal(FARGS
,"No or not correct number (2) of output-files: %d",nfspect
);
662 powerspectavg(intfpos
, frames
,xslices
,yslices
,spectra
);
667 nfraw
=opt2fns(&raw
,"-or",NFILE
,fnm
);
670 gmx_fatal(FARGS
,"No or not correct number (2) of output-files: %d",nfraw
);
672 writeraw(intfpos
,frames
,xslices
,yslices
,raw
);