3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * Green Red Orange Magenta Azure Cyan Skyblue
52 static void calc_com_pbc(int nrefat
,t_topology
*top
,rvec x
[],t_pbc
*pbc
,
53 atom_id index
[],rvec xref
,bool bPBC
,matrix box
)
61 /* First simple calculation */
64 for(m
=0; (m
<nrefat
); m
++) {
66 mass
= top
->atoms
.atom
[ai
].m
;
67 for(j
=0; (j
<DIM
); j
++)
68 xref
[j
] += mass
*x
[ai
][j
];
71 svmul(1/mtot
,xref
,xref
);
72 /* Now check if any atom is more than half the box from the COM */
77 for(m
=0; (m
<nrefat
); m
++) {
79 mass
= top
->atoms
.atom
[ai
].m
/mtot
;
80 pbc_dx(pbc
,x
[ai
],xref
,dx
);
81 rvec_add(xref
,dx
,xtest
);
82 for(j
=0; (j
<DIM
); j
++)
83 if (fabs(xtest
[j
]-x
[ai
][j
]) > tol
) {
84 /* Here we have used the wrong image for contributing to the COM */
85 xref
[j
] += mass
*(xtest
[j
]-x
[ai
][j
]);
91 printf("COM: %8.3f %8.3f %8.3f iter = %d\n",xref
[XX
],xref
[YY
],xref
[ZZ
],iter
);
97 int gmx_sorient(int argc
,char *argv
[])
109 int i
,j
,p
,sa0
,sa1
,sa2
,n
,ntot
,nf
,m
,*hist1
,*hist2
,*histn
,nbin1
,nbin2
,nrbin
;
110 real
*histi1
,*histi2
,invbw
,invrbw
;
112 int *isize
,nrefgrp
,nrefat
;
115 real inp
,outp
,two_pi
,nav
,normfac
,rmin2
,rmax2
,rcut
,rcut2
,r2
,r
,mass
,mtot
;
119 rvec xref
,dx
,dxh1
,dxh2
,outer
;
121 char *legr
[] = { "<cos(\\8q\\4\\s1\\N)>",
122 "<3cos\\S2\\N(\\8q\\4\\s2\\N)-1>" };
123 char *legc
[] = { "cos(\\8q\\4\\s1\\N)",
124 "3cos\\S2\\N(\\8q\\4\\s2\\N)-1" };
126 const char *desc
[] = {
127 "g_sorient analyzes solvent orientation around solutes.",
128 "It calculates two angles between the vector from one or more",
129 "reference positions to the first atom of each solvent molecule:[BR]",
130 "theta1: the angle with the vector from the first atom of the solvent",
131 "molecule to the midpoint between atoms 2 and 3.[BR]",
132 "theta2: the angle with the normal of the solvent plane, defined by the",
133 "same three atoms, or when the option [TT]-v23[tt] is set",
134 "the angle with the vector between atoms 2 and 3.[BR]",
135 "The reference can be a set of atoms or",
136 "the center of mass of a set of atoms. The group of solvent atoms should",
137 "consist of 3 atoms per solvent molecule.",
138 "Only solvent molecules between [TT]-rmin[tt] and [TT]-rmax[tt] are",
139 "considered for [TT]-o[tt] and [TT]-no[tt] each frame.[PAR]",
140 "[TT]-o[tt]: distribtion of cos(theta1) for rmin<=r<=rmax.[PAR]",
141 "[TT]-no[tt]: distribution of cos(theta2) for rmin<=r<=rmax.[PAR]",
142 "[TT]-ro[tt]: <cos(theta1)> and <3cos^2(theta2)-1> as a function of the",
144 "[TT]-co[tt]: the sum over all solvent molecules within distance r",
145 "of cos(theta1) and 3cos^2(theta2)-1 as a function of r.[PAR]",
146 "[TT]-rc[tt]: the distribution of the solvent molecules as a function of r"
150 static bool bCom
= FALSE
,bVec23
=FALSE
,bPBC
= FALSE
;
151 static real rmin
=0.0,rmax
=0.5,binwidth
=0.02,rbinw
=0.02;
153 { "-com", FALSE
, etBOOL
, {&bCom
},
154 "Use the center of mass as the reference postion" },
155 { "-v23", FALSE
, etBOOL
, {&bVec23
},
156 "Use the vector between atoms 2 and 3" },
157 { "-rmin", FALSE
, etREAL
, {&rmin
}, "Minimum distance (nm)" },
158 { "-rmax", FALSE
, etREAL
, {&rmax
}, "Maximum distance (nm)" },
159 { "-cbin", FALSE
, etREAL
, {&binwidth
}, "Binwidth for the cosine" },
160 { "-rbin", FALSE
, etREAL
, {&rbinw
}, "Binwidth for r (nm)" },
161 { "-pbc", FALSE
, etBOOL
, {&bPBC
}, "Check PBC for the center of mass calculation. Only necessary when your reference group consists of several molecules." }
165 { efTRX
, NULL
, NULL
, ffREAD
},
166 { efTPS
, NULL
, NULL
, ffREAD
},
167 { efNDX
, NULL
, NULL
, ffOPTRD
},
168 { efXVG
, NULL
, "sori.xvg", ffWRITE
},
169 { efXVG
, "-no", "snor.xvg", ffWRITE
},
170 { efXVG
, "-ro", "sord.xvg", ffWRITE
},
171 { efXVG
, "-co", "scum.xvg", ffWRITE
},
172 { efXVG
, "-rc", "scount.xvg", ffWRITE
}
174 #define NFILE asize(fnm)
176 CopyRight(stderr
,argv
[0]);
177 parse_common_args(&argc
,argv
,PCA_CAN_TIME
| PCA_CAN_VIEW
| PCA_BE_NICE
,
178 NFILE
,fnm
,asize(pa
),pa
,asize(desc
),desc
,0,NULL
,&oenv
);
182 bTPS
= (opt2bSet("-s",NFILE
,fnm
) || !opt2bSet("-n",NFILE
,fnm
) || bCom
);
184 read_tps_conf(ftp2fn(efTPS
,NFILE
,fnm
),title
,&top
,&ePBC
,&xtop
,NULL
,box
,
188 /* get index groups */
189 printf("Select a group of reference particles and a solvent group:\n");
194 get_index(&top
.atoms
,ftp2fn_null(efNDX
,NFILE
,fnm
),2,isize
,index
,grpname
);
196 get_index(NULL
,ftp2fn(efNDX
,NFILE
,fnm
),2,isize
,index
,grpname
);
208 gmx_fatal(FARGS
,"The number of solvent atoms (%d) is not a multiple of 3",
211 /* initialize reading trajectory: */
212 natoms
=read_first_x(oenv
,&status
,ftp2fn(efTRX
,NFILE
,fnm
),&t
,&x
,box
);
216 rcut
= 0.99*sqrt(max_cutoff2(guess_ePBC(box
),box
));
222 nbin1
= (int)(2*invbw
+ 0.5);
223 nbin2
= (int)(invbw
+ 0.5);
241 /* start analysis of trajectory */
244 /* make molecules whole again */
245 rm_pbc(&top
.idef
,ePBC
,natoms
,box
,x
,x
);
248 set_pbc(&pbc
,ePBC
,box
);
252 for(p
=0; (p
<nrefgrp
); p
++) {
254 calc_com_pbc(nrefat
,&top
,x
,&pbc
,index
[0],xref
,bPBC
,box
);
256 copy_rvec(x
[index
[0][p
]],xref
);
258 for(m
=0; m
<isize
[1]; m
+=3) {
262 pbc_dx(&pbc
,x
[sa0
],xref
,dx
);
267 /* Determine the normal to the plain */
268 rvec_sub(x
[sa1
],x
[sa0
],dxh1
);
269 rvec_sub(x
[sa2
],x
[sa0
],dxh2
);
273 inp
= iprod(dx
,dxh1
);
274 cprod(dxh1
,dxh2
,outer
);
276 outp
= iprod(dx
,outer
);
278 /* Use the vector between the 2nd and 3rd atom */
279 rvec_sub(x
[sa2
],x
[sa1
],dxh2
);
281 outp
= iprod(dx
,dxh2
)/r
;
283 (histi1
[(int)(invrbw
*r
)]) += inp
;
284 (histi2
[(int)(invrbw
*r
)]) += 3*sqr(outp
) - 1;
285 (histn
[(int)(invrbw
*r
)])++;
286 if (r2
>=rmin2
&& r2
<rmax2
) {
287 (hist1
[(int)(invbw
*(inp
+ 1))])++;
288 (hist2
[(int)(invbw
*fabs(outp
))])++;
299 } while (read_next_x(oenv
,status
,&t
,natoms
,x
,box
));
305 /* Add the bin for the exact maximum to the previous bin */
306 hist1
[nbin1
-1] += hist1
[nbin1
];
307 hist2
[nbin2
-1] += hist2
[nbin2
];
309 nav
= (real
)ntot
/(nrefgrp
*nf
);
310 normfac
= invbw
/ntot
;
312 fprintf(stderr
, "Average nr of molecules between %g and %g nm: %.1f\n",
317 fprintf(stderr
,"Average cos(theta1) between %g and %g nm: %6.3f\n",
319 fprintf(stderr
,"Average 3cos2(theta2)-1 between %g and %g nm: %6.3f\n",
323 sprintf(str
,"Solvent orientation between %g and %g nm",rmin
,rmax
);
324 fp
=xvgropen(opt2fn("-o",NFILE
,fnm
), str
,"cos(\\8q\\4\\s1\\N)","",oenv
);
325 if (output_env_get_print_xvgr_codes(oenv
))
326 fprintf(fp
,"@ subtitle \"average shell size %.1f molecules\"\n",nav
);
327 for(i
=0; i
<nbin1
; i
++) {
328 fprintf(fp
,"%g %g\n",(i
+0.5)*binwidth
-1,2*normfac
*hist1
[i
]);
332 sprintf(str
,"Solvent normal orientation between %g and %g nm",rmin
,rmax
);
333 fp
=xvgropen(opt2fn("-no",NFILE
,fnm
), str
,"cos(\\8q\\4\\s2\\N)","",oenv
);
334 if (output_env_get_print_xvgr_codes(oenv
))
335 fprintf(fp
,"@ subtitle \"average shell size %.1f molecules\"\n",nav
);
336 for(i
=0; i
<nbin2
; i
++) {
337 fprintf(fp
,"%g %g\n",(i
+0.5)*binwidth
,normfac
*hist2
[i
]);
342 sprintf(str
,"Solvent orientation");
343 fp
=xvgropen(opt2fn("-ro",NFILE
,fnm
),str
,"r (nm)","",oenv
);
344 if (output_env_get_print_xvgr_codes(oenv
))
345 fprintf(fp
,"@ subtitle \"as a function of distance\"\n");
346 xvgr_legend(fp
,2,legr
,oenv
);
347 for(i
=0; i
<nrbin
; i
++)
348 fprintf(fp
,"%g %g %g\n",(i
+0.5)*rbinw
,
349 histn
[i
] ? histi1
[i
]/histn
[i
] : 0,
350 histn
[i
] ? histi2
[i
]/histn
[i
] : 0);
353 sprintf(str
,"Cumulative solvent orientation");
354 fp
=xvgropen(opt2fn("-co",NFILE
,fnm
),str
,"r (nm)","",oenv
);
355 if (output_env_get_print_xvgr_codes(oenv
))
356 fprintf(fp
,"@ subtitle \"as a function of distance\"\n");
357 xvgr_legend(fp
,2,legc
,oenv
);
358 normfac
= 1.0/(nrefgrp
*nf
);
361 fprintf(fp
,"%g %g %g\n",0.0,c1
,c2
);
362 for(i
=0; i
<nrbin
; i
++) {
363 c1
+= histi1
[i
]*normfac
;
364 c2
+= histi2
[i
]*normfac
;
365 fprintf(fp
,"%g %g %g\n",(i
+1)*rbinw
,c1
,c2
);
369 sprintf(str
,"Solvent distribution");
370 fp
=xvgropen(opt2fn("-rc",NFILE
,fnm
),str
,"r (nm)","molecules/nm",oenv
);
371 if (output_env_get_print_xvgr_codes(oenv
))
372 fprintf(fp
,"@ subtitle \"as a function of distance\"\n");
373 normfac
= 1.0/(rbinw
*nf
);
374 for(i
=0; i
<nrbin
; i
++) {
375 fprintf(fp
,"%g %g\n",(i
+0.5)*rbinw
,histn
[i
]*normfac
);
379 do_view(oenv
, opt2fn("-o",NFILE
,fnm
),NULL
);
380 do_view(oenv
, opt2fn("-no",NFILE
,fnm
),NULL
);
381 do_view(oenv
, opt2fn("-ro",NFILE
,fnm
),"-nxy");
382 do_view(oenv
, opt2fn("-co",NFILE
,fnm
),"-nxy");