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 #include "gmx_statistics.h"
65 #define e2d(x) ENM2DEBYE*(x)
66 #define EANG2CM E_CHARGE*1.0e-10 /* e Angstrom to Coulomb meter */
67 #define CM2D SPEED_OF_LIGHT*1.0e+24 /* Coulomb meter to Debye */
79 static t_gkrbin
*mk_gkrbin(real radius
,real rcmax
,bool bPhi
,int ndegrees
)
87 if ((ptr
= getenv("GKRWIDTH")) != NULL
) {
90 sscanf(ptr
,"%lf",&bw
);
94 gb
->spacing
= 0.01; /* nm */
95 gb
->nelem
= 1 + radius
/gb
->spacing
;
99 gb
->nx
= 1 + rcmax
/gb
->spacing
;
101 snew(gb
->elem
,gb
->nelem
);
102 snew(gb
->count
,gb
->nelem
);
104 snew(gb
->cmap
,gb
->nx
);
105 gb
->ny
= max(2,ndegrees
);
106 for(i
=0; (i
<gb
->nx
); i
++)
107 snew(gb
->cmap
[i
],gb
->ny
);
113 static void done_gkrbin(t_gkrbin
**gb
)
121 static void add2gkr(t_gkrbin
*gb
,real r
,real cosa
,real phi
)
123 int cy
,index
= gmx_nint(r
/gb
->spacing
);
126 if (index
< gb
->nelem
) {
127 gb
->elem
[index
] += cosa
;
130 if (index
< gb
->nx
) {
133 cy
= (M_PI
+phi
)*gb
->ny
/(2*M_PI
);
135 cy
= (alpha
*gb
->ny
)/M_PI
;/*((1+cosa)*0.5*(gb->ny));*/
136 cy
= min(gb
->ny
-1,max(0,cy
));
138 fprintf(debug
,"CY: %10f %5d\n",alpha
,cy
);
139 gb
->cmap
[index
][cy
] += 1;
143 static void rvec2sprvec(rvec dipcart
,rvec dipsp
)
146 dipsp
[0] = sqrt(dipcart
[XX
]*dipcart
[XX
]+dipcart
[YY
]*dipcart
[YY
]+dipcart
[ZZ
]*dipcart
[ZZ
]); /* R */
147 dipsp
[1] = atan2(dipcart
[YY
],dipcart
[XX
]); /* Theta */
148 dipsp
[2] = atan2(sqrt(dipcart
[XX
]*dipcart
[XX
]+dipcart
[YY
]*dipcart
[YY
]),dipcart
[ZZ
]); /* Phi */
153 void do_gkr(t_gkrbin
*gb
,int ncos
,int *ngrp
,int *molindex
[],
154 int mindex
[],rvec x
[],rvec mu
[],
155 int ePBC
,matrix box
,t_atom
*atom
,int *nAtom
)
157 static rvec
*xcm
[2] = { NULL
, NULL
};
158 int gi
,gj
,j0
,j1
,i
,j
,k
,n
,index
,grp0
,grp1
;
159 real qtot
,q
,r2
,cosa
,rr
,phi
;
163 for(n
=0; (n
<ncos
); n
++) {
165 snew(xcm
[n
],ngrp
[n
]);
166 for(i
=0; (i
<ngrp
[n
]); i
++) {
167 /* Calculate center of mass of molecule */
172 copy_rvec(x
[j0
+nAtom
[n
]-1],xcm
[n
][i
]);
175 clear_rvec(xcm
[n
][i
]);
177 for(j
=j0
; j
<j1
; j
++) {
181 xcm
[n
][i
][k
] += q
*x
[j
][k
];
183 svmul(1/qtot
,xcm
[n
][i
],xcm
[n
][i
]);
187 set_pbc(&pbc
,ePBC
,box
);
190 for(i
=0; i
<ngrp
[grp0
]; i
++) {
191 gi
= molindex
[grp0
][i
];
192 j0
= (ncos
== 2) ? 0 : i
+1;
193 for(j
=j0
; j
<ngrp
[grp1
]; j
++) {
194 gj
= molindex
[grp1
][j
];
195 if ((iprod(mu
[gi
],mu
[gi
]) > 0) && (iprod(mu
[gj
],mu
[gj
]) > 0)) {
196 /* Compute distance between molecules including PBC */
197 pbc_dx(&pbc
,xcm
[grp0
][i
],xcm
[grp1
][j
],dx
);
202 rvec r_ij
,r_kj
,r_kl
,mm
,nn
;
206 copy_rvec(xcm
[grp0
][i
],xj
);
207 copy_rvec(xcm
[grp1
][j
],xk
);
208 rvec_add(xj
,mu
[gi
],xi
);
209 rvec_add(xk
,mu
[gj
],xl
);
210 phi
= dih_angle(xi
,xj
,xk
,xl
,&pbc
,
211 r_ij
,r_kj
,r_kl
,mm
,nn
, /* out */
216 cosa
= cos_angle(mu
[gi
],mu
[gj
]);
219 if (debug
|| (cosa
!= cosa
)) {
220 fprintf(debug
? debug
: stderr
,
221 "mu[%d] = %5.2f %5.2f %5.2f |mi| = %5.2f, mu[%d] = %5.2f %5.2f %5.2f |mj| = %5.2f rr = %5.2f cosa = %5.2f\n",
222 gi
,mu
[gi
][XX
],mu
[gi
][YY
],mu
[gi
][ZZ
],norm(mu
[gi
]),
223 gj
,mu
[gj
][XX
],mu
[gj
][YY
],mu
[gj
][ZZ
],norm(mu
[gj
]),
227 add2gkr(gb
,rr
,cosa
,phi
);
233 static real
normalize_cmap(t_gkrbin
*gb
)
239 for(i
=0; (i
<gb
->nx
); i
++) {
240 vol
= 4*M_PI
*sqr(gb
->spacing
*i
)*gb
->spacing
;
241 for(j
=0; (j
<gb
->ny
); j
++) {
242 gb
->cmap
[i
][j
] /= vol
;
243 hi
= max(hi
,gb
->cmap
[i
][j
]);
247 gmx_fatal(FARGS
,"No data in the cmap");
251 static void print_cmap(const char *cmap
,t_gkrbin
*gb
,int *nlevels
)
258 t_rgb rlo
= { 1, 1, 1 };
259 t_rgb rhi
= { 0, 0, 0 };
261 hi
= normalize_cmap(gb
);
262 snew(xaxis
,gb
->nx
+1);
263 for(i
=0; (i
<gb
->nx
+1); i
++)
264 xaxis
[i
] = i
*gb
->spacing
;
266 for(j
=0; (j
<gb
->ny
); j
++) {
268 yaxis
[j
] = (360.0*j
)/(gb
->ny
-1.0)-180;
270 yaxis
[j
] = (180.0*j
)/(gb
->ny
-1.0);
271 /*2.0*j/(gb->ny-1.0)-1.0;*/
273 out
= ffopen(cmap
,"w");
275 "Dipole Orientation Distribution","Fraction","r (nm)",
276 gb
->bPhi
? "Phi" : "Alpha",
277 gb
->nx
,gb
->ny
,xaxis
,yaxis
,
278 gb
->cmap
,0,hi
,rlo
,rhi
,nlevels
);
284 static void print_gkrbin(const char *fn
,t_gkrbin
*gb
,
285 int ngrp
,int nframes
,real volume
,
286 const output_env_t oenv
)
288 /* We compute Gk(r), gOO and hOO according to
289 * Nymand & Linse, JCP 112 (2000) pp 6386-6395.
290 * In this implementation the angle between dipoles is stored
291 * rather than their inner product. This allows to take polarizible
292 * models into account. The RDF is calculated as well, almost for free!
295 char *leg
[] = { "G\\sk\\N(r)", "< cos >", "h\\sOO\\N", "g\\sOO\\N", "Energy" };
297 real x0
,x1
,ggg
,Gkr
,vol_s
,rho
,gOO
,hOO
,cosav
,ener
;
300 fp
=xvgropen(fn
,"Distance dependent Gk","r (nm)","G\\sk\\N(r)",oenv
);
301 xvgr_legend(fp
,asize(leg
),leg
,oenv
);
303 Gkr
= 1; /* Self-dipole inproduct = 1 */
307 fprintf(debug
,"Number density is %g molecules / nm^3\n",rho
);
308 fprintf(debug
,"ngrp = %d, nframes = %d\n",ngrp
,nframes
);
312 while(last
>1 && gb
->elem
[last
-1]==0)
315 /* Divide by dipole squared, by number of frames, by number of origins.
316 * Multiply by 2 because we only take half the matrix of interactions
319 fac
= 2.0/((double) ngrp
* (double) nframes
);
322 for(i
=0; i
<last
; i
++) {
323 /* Centre of the coordinate in the spherical layer */
326 /* Volume of the layer */
327 vol_s
= (4.0/3.0)*M_PI
*(x1
*x1
*x1
-x0
*x0
*x0
);
330 gOO
= gb
->count
[i
]*fac
/(rho
*vol_s
);
332 /* Dipole correlation hOO, normalized by the relative number density, like
333 * in a Radial distribution function.
335 ggg
= gb
->elem
[i
]*fac
;
336 hOO
= 3.0*ggg
/(rho
*vol_s
);
339 cosav
= gb
->elem
[i
]/gb
->count
[i
];
342 ener
= -0.5*cosav
*ONE_4PI_EPS0
/(x1
*x1
*x1
);
344 fprintf(fp
,"%10.5e %12.5e %12.5e %12.5e %12.5e %12.5e\n",
345 x1
,Gkr
,cosav
,hOO
,gOO
,ener
);
353 bool read_mu_from_enx(ener_file_t fmu
,int Vol
,ivec iMu
,rvec mu
,real
*vol
,
354 real
*t
, int nre
,t_enxframe
*fr
)
360 bCont
= do_enx(fmu
,fr
);
362 fprintf(stderr
,"Something strange: expected %d entries in energy file at step %s\n(time %g) but found %d entries\n",
363 nre
,gmx_step_str(fr
->step
,buf
),fr
->t
,fr
->nre
);
366 if (Vol
!= -1) /* we've got Volume in the energy file */
367 *vol
= fr
->ener
[Vol
].e
;
368 for (i
=0; i
<DIM
; i
++)
369 mu
[i
] = fr
->ener
[iMu
[i
]].e
;
376 static void neutralize_mols(int n
,int *index
,t_block
*mols
,t_atom
*atom
)
379 int ncharged
,m
,a0
,a1
,a
;
383 a0
= mols
->index
[index
[m
]];
384 a1
= mols
->index
[index
[m
]+1];
387 for(a
=a0
; a
<a1
; a
++) {
391 /* This check is only for the count print */
392 if (fabs(qtot
) > 0.01)
395 /* Remove the net charge at the center of mass */
397 atom
[a
].q
-= qtot
*atom
[a
].m
/mtot
;
402 printf("There are %d charged molecules in the selection,\n"
403 "will subtract their charge at their center of mass\n",ncharged
);
406 static void mol_dip(int k0
,int k1
,rvec x
[],t_atom atom
[],rvec mu
)
412 for(k
=k0
; (k
<k1
); k
++) {
414 for(m
=0; (m
<DIM
); m
++)
419 static void mol_quad(int k0
,int k1
,rvec x
[],t_atom atom
[],rvec quad
)
422 real q
,r2
,mass
,masstot
;
423 rvec com
; /* center of mass */
424 rvec r
; /* distance of atoms to center of mass */
427 double dd
[DIM
],**ev
,tmp
;
431 for(i
=0; (i
<DIM
); i
++) {
437 /* Compute center of mass */
440 for(k
=k0
; (k
<k1
); k
++) {
443 for(i
=0; (i
<DIM
); i
++)
444 com
[i
] += mass
*x
[k
][i
];
446 svmul((1.0/masstot
),com
,com
);
448 /* We want traceless quadrupole moments, so let us calculate the complete
449 * quadrupole moment tensor and diagonalize this tensor to get
450 * the individual components on the diagonal.
453 #define delta(a,b) (( a == b ) ? 1.0 : 0.0)
455 for(m
=0; (m
<DIM
); m
++)
456 for(n
=0; (n
<DIM
); n
++)
458 for(k
=k0
; (k
<k1
); k
++) { /* loop over atoms in a molecule */
459 q
= (atom
[k
].q
)*100.0;
460 rvec_sub(x
[k
],com
,r
);
462 for(m
=0; (m
<DIM
); m
++)
463 for(n
=0; (n
<DIM
); n
++)
464 inten
[m
][n
] += 0.5*q
*(3.0*r
[m
]*r
[n
] - r2
*delta(m
,n
))*EANG2CM
*CM2D
;
467 for(i
=0; (i
<DIM
); i
++)
468 fprintf(debug
,"Q[%d] = %8.3f %8.3f %8.3f\n",
469 i
,inten
[i
][XX
],inten
[i
][YY
],inten
[i
][ZZ
]);
471 /* We've got the quadrupole tensor, now diagonalize the sucker */
472 jacobi(inten
,3,dd
,ev
,&niter
);
475 for(i
=0; (i
<DIM
); i
++)
476 fprintf(debug
,"ev[%d] = %8.3f %8.3f %8.3f\n",
477 i
,ev
[i
][XX
],ev
[i
][YY
],ev
[i
][ZZ
]);
478 for(i
=0; (i
<DIM
); i
++)
479 fprintf(debug
,"Q'[%d] = %8.3f %8.3f %8.3f\n",
480 i
,inten
[i
][XX
],inten
[i
][YY
],inten
[i
][ZZ
]);
482 /* Sort the eigenvalues, for water we know that the order is as follows:
486 * At the moment I have no idea how this will work out for other molecules...
490 if (dd[i+1] > dd[i]) { \
499 for(m
=0; (m
<DIM
); m
++) {
500 quad
[0]=dd
[2]; /* yy */
501 quad
[1]=dd
[0]; /* zz */
502 quad
[2]=dd
[1]; /* xx */
506 pr_rvec(debug
,0,"Quadrupole",quad
,DIM
,TRUE
);
509 for(i
=0; (i
<DIM
); i
++) {
518 * Calculates epsilon according to M. Neumann, Mol. Phys. 50, 841 (1983)
520 real
calc_eps(double M_diff
,double volume
,double epsRF
,double temp
)
522 double eps
,A
,teller
,noemer
;
523 double eps_0
=8.854187817e-12; /* epsilon_0 in C^2 J^-1 m^-1 */
524 double fac
=1.112650021e-59; /* converts Debye^2 to C^2 m^2 */
526 A
= M_diff
*fac
/(3*eps_0
*volume
*NANO
*NANO
*NANO
*BOLTZMANN
*temp
);
532 teller
= 1 + (A
*2*epsRF
/(2*epsRF
+1));
533 noemer
= 1 - (A
/(2*epsRF
+1));
535 eps
= teller
/ noemer
;
540 static void update_slab_dipoles(int k0
,int k1
,rvec x
[],rvec mu
,
541 int idim
,int nslice
,rvec slab_dipole
[],
547 for(k
=k0
; (k
<k1
); k
++)
550 k
= ((int)(xdim
*nslice
/box
[idim
][idim
] + nslice
)) % nslice
;
551 rvec_inc(slab_dipole
[k
],mu
);
554 static void dump_slab_dipoles(const char *fn
,int idim
,int nslice
,
555 rvec slab_dipole
[], matrix box
,int nframes
,
556 const output_env_t oenv
)
563 "\\f{12}m\\f{4}\\sX\\N",
564 "\\f{12}m\\f{4}\\sY\\N",
565 "\\f{12}m\\f{4}\\sZ\\N",
566 "\\f{12}m\\f{4}\\stot\\N"
569 sprintf(buf
,"Box-%c (nm)",'X'+idim
);
570 fp
= xvgropen(fn
,"Average dipole moment per slab",buf
,"\\f{12}m\\f{4} (D)",
572 xvgr_legend(fp
,DIM
,leg_dim
,oenv
);
573 for(i
=0; (i
<nslice
); i
++) {
574 mutot
= norm(slab_dipole
[i
])/nframes
;
575 fprintf(fp
,"%10.3f %10.3f %10.3f %10.3f %10.3f\n",
576 ((i
+0.5)*box
[idim
][idim
])/nslice
,
577 slab_dipole
[i
][XX
]/nframes
,
578 slab_dipole
[i
][YY
]/nframes
,
579 slab_dipole
[i
][ZZ
]/nframes
,
583 do_view(oenv
,fn
,"-autoscale xy -nxy");
586 static void compute_avercos(int n
,rvec dip
[],real
*dd
,rvec axis
,bool bPairs
)
589 double dc
,dc1
,d
,n5
,ddc1
,ddc2
,ddc3
;
590 rvec xxx
= { 1, 0, 0 };
591 rvec yyy
= { 0, 1, 0 };
592 rvec zzz
= { 0, 0, 1 };
595 ddc1
= ddc2
= ddc3
= 0;
596 for(i
=k
=0; (i
<n
); i
++) {
597 ddc1
+= fabs(cos_angle(dip
[i
],xxx
));
598 ddc2
+= fabs(cos_angle(dip
[i
],yyy
));
599 ddc3
+= fabs(cos_angle(dip
[i
],zzz
));
601 for(j
=i
+1; (j
<n
); j
++,k
++) {
602 dc
= cos_angle(dip
[i
],dip
[j
]);
612 static void do_dip(t_topology
*top
,int ePBC
,real volume
,
614 const char *out_mtot
,const char *out_eps
,
615 const char *out_aver
, const char *dipdist
,
616 const char *cosaver
, const char *fndip3d
,
617 const char *fnadip
, bool bPairs
,
618 const char *corrtype
,const char *corf
,
619 bool bGkr
, const char *gkrfn
,
620 bool bPhi
, int *nlevels
, int ndegrees
,
622 const char *cmap
, real rcmax
,
623 bool bQuad
, const char *quadfn
,
624 bool bMU
, const char *mufn
,
625 int *gnx
, int *molindex
[],
626 real mu_max
, real mu_aver
,
627 real epsilonRF
,real temp
,
628 int *gkatom
, int skip
,
629 bool bSlab
, int nslices
,
630 const char *axtitle
, const char *slabfn
,
631 const output_env_t oenv
)
639 #define NLEGMTOT asize(leg_mtot)
645 #define NLEGEPS asize(leg_eps)
649 "< |M|\\S2\\N > - < |M| >\\S2\\N",
650 "< |M| >\\S2\\N / < |M|\\S2\\N >"
652 #define NLEGAVER asize(leg_aver)
653 char *leg_cosaver
[] = {
654 "\\f{4}<|cos\\f{12}q\\f{4}\\sij\\N|>",
656 "\\f{4}<|cos\\f{12}q\\f{4}\\siX\\N|>",
657 "\\f{4}<|cos\\f{12}q\\f{4}\\siY\\N|>",
658 "\\f{4}<|cos\\f{12}q\\f{4}\\siZ\\N|>"
660 #define NLEGCOSAVER asize(leg_cosaver)
666 #define NLEGADIP asize(leg_adip)
668 FILE *outdd
,*outmtot
,*outaver
,*outeps
,*caver
=NULL
;
669 FILE *dip3d
=NULL
,*adip
=NULL
;
670 rvec
*x
,*dipole
=NULL
,mu_t
,quad
,*dipsp
=NULL
;
671 t_gkrbin
*gkrbin
= NULL
;
672 gmx_enxnm_t
*enm
=NULL
;
674 int nframes
=1000,nre
,timecheck
=0,ncolour
=0;
675 ener_file_t fmu
=NULL
;
676 int i
,j
,k
,n
,m
,natom
=0,nmol
,status
,gnx_tot
,teller
,tel3
;
677 int *dipole_bin
,ndipbin
,ibin
,iVol
,step
,idim
=-1;
680 real rcut
=0,t
,t0
,t1
,dt
,lambda
,dd
,rms_cos
;
683 bool bCorr
,bTotal
,bCont
;
684 double M_diff
=0,epsilon
,invtel
,vol_aver
;
685 double mu_ave
,mu_mol
,M2_ave
=0,M_ave2
=0,M_av
[DIM
],M_av2
[DIM
];
686 double M
[3],M2
[3],M4
[3],Gk
=0,g_k
=0;
687 gmx_stats_t Mx
,My
,Mz
,Msq
,Vol
,*Qlsq
,mulsq
,muframelsq
=NULL
;
690 rvec
*slab_dipoles
=NULL
;
703 fmu
= open_enx(mufn
,"r");
704 do_enxnms(fmu
,&nre
,&enm
);
706 /* Determine the indexes of the energy grps we need */
707 for (i
=0; (i
<nre
); i
++) {
708 if (strstr(enm
[i
].name
,"Volume"))
710 else if (strstr(enm
[i
].name
,"Mu-X"))
712 else if (strstr(enm
[i
].name
,"Mu-Y"))
714 else if (strstr(enm
[i
].name
,"Mu-Z"))
719 atom
= top
->atoms
.atom
;
724 printf("Using Volume from topology: %g nm^3\n",volume
);
726 /* Correlation stuff */
727 bCorr
= (corrtype
[0] != 'n');
728 bTotal
= (corrtype
[0] == 't');
732 snew(muall
[0],nframes
*DIM
);
736 for(i
=0; (i
<gnx
[0]); i
++)
737 snew(muall
[i
],nframes
*DIM
);
741 /* Allocate array which contains for every molecule in a frame the
745 snew(dipole
,gnx_tot
);
749 for(i
=0; (i
<DIM
); i
++)
750 Qlsq
[i
] = gmx_stats_init();
751 mulsq
= gmx_stats_init();
753 /* Open all the files */
754 outmtot
= xvgropen(out_mtot
,
755 "Total dipole moment of the simulation box vs. time",
756 "Time (ps)","Total Dipole Moment (Debye)",oenv
);
757 outeps
= xvgropen(out_eps
,"Epsilon and Kirkwood factors",
758 "Time (ps)","",oenv
);
759 outaver
= xvgropen(out_aver
,"Total dipole moment",
760 "Time (ps)","D",oenv
);
762 idim
= axtitle
[0] - 'X';
763 if ((idim
< 0) || (idim
>= DIM
))
764 idim
= axtitle
[0] - 'x';
765 if ((idim
< 0) || (idim
>= DIM
))
769 fprintf(stderr
,"axtitle = %s, nslices = %d, idim = %d\n",
770 axtitle
,nslices
,idim
);
772 snew(slab_dipoles
,nslices
);
773 fprintf(stderr
,"Doing slab analysis\n");
778 adip
= xvgropen(fnadip
, "Average molecular dipole","Dipole (D)","",oenv
);
779 xvgr_legend(adip
,NLEGADIP
,leg_adip
, oenv
);
783 caver
= xvgropen(cosaver
,bPairs
? "Average pair orientation" :
784 "Average absolute dipole orientation","Time (ps)","",oenv
);
785 xvgr_legend(caver
,NLEGCOSAVER
,bPairs
? leg_cosaver
: &(leg_cosaver
[1]),
792 /* we need a dummy file for gnuplot */
793 dip3d
= (FILE *)ffopen("dummy.dat","w");
794 fprintf(dip3d
,"%f %f %f", 0.0,0.0,0.0);
797 dip3d
= (FILE *)ffopen(fndip3d
,"w");
798 fprintf(dip3d
,"# This file was created by %s\n",Program());
799 fprintf(dip3d
,"# which is part of G R O M A C S:\n");
800 fprintf(dip3d
,"#\n");
803 /* Write legends to all the files */
804 xvgr_legend(outmtot
,NLEGMTOT
,leg_mtot
,oenv
);
805 xvgr_legend(outaver
,NLEGAVER
,leg_aver
,oenv
);
807 if (bMU
&& (mu_aver
== -1))
808 xvgr_legend(outeps
,NLEGEPS
-2,leg_eps
,oenv
);
810 xvgr_legend(outeps
,NLEGEPS
,leg_eps
,oenv
);
815 /* Read the first frame from energy or traj file */
818 bCont
= read_mu_from_enx(fmu
,iVol
,iMu
,mu_t
,&volume
,&t
,nre
,fr
);
820 timecheck
=check_times(t
);
823 if ((teller
% 10) == 0)
824 fprintf(stderr
,"\r Skipping Frame %6d, time: %8.3f", teller
, t
);
827 printf("End of %s reached\n",mufn
);
830 } while (bCont
&& (timecheck
< 0));
832 natom
= read_first_x(oenv
,&status
,fn
,&t
,&x
,box
);
834 /* Calculate spacing for dipole bin (simple histogram) */
835 ndipbin
= 1+(mu_max
/0.01);
836 snew(dipole_bin
, ndipbin
);
839 for(m
=0; (m
<DIM
); m
++) {
840 M
[m
] = M2
[m
] = M4
[m
] = 0.0;
844 /* Use 0.7 iso 0.5 to account for pressure scaling */
845 /* rcut = 0.7*sqrt(max_cutoff2(box)); */
846 rcut
= 0.7*sqrt(sqr(box
[XX
][XX
])+sqr(box
[YY
][YY
])+sqr(box
[ZZ
][ZZ
]));
848 gkrbin
= mk_gkrbin(rcut
,rcmax
,bPhi
,ndegrees
);
851 /* Start while loop over frames */
855 if (bCorr
&& (teller
>= nframes
)) {
858 srenew(muall
[0],nframes
*DIM
);
861 for(i
=0; (i
<gnx_tot
); i
++)
862 srenew(muall
[i
],nframes
*DIM
);
868 /* Copy rvec into double precision local variable */
869 for(m
=0; (m
<DIM
); m
++)
874 for(m
=0; (m
<DIM
); m
++) {
878 rm_pbc(&(top
->idef
),ePBC
,natom
,box
,x
,x
);
880 muframelsq
= gmx_stats_init();
881 /* Begin loop of all molecules in frame */
882 for(n
=0; (n
<ncos
); n
++) {
883 for(i
=0; (i
<gnx
[n
]); i
++) {
886 ind0
= mols
->index
[molindex
[n
][i
]];
887 ind1
= mols
->index
[molindex
[n
][i
]+1];
889 mol_dip(ind0
,ind1
,x
,atom
,dipole
[i
]);
890 gmx_stats_add_point(mulsq
,0,norm(dipole
[i
]),0,0);
891 gmx_stats_add_point(muframelsq
,0,norm(dipole
[i
]),0,0);
893 update_slab_dipoles(ind0
,ind1
,x
,
894 dipole
[i
],idim
,nslices
,slab_dipoles
,box
);
896 mol_quad(ind0
,ind1
,x
,atom
,quad
);
897 for(m
=0; (m
<DIM
); m
++)
898 gmx_stats_add_point(Qlsq
[m
],0,quad
[m
],0,0);
900 if (bCorr
&& !bTotal
) {
902 muall
[i
][tel3
+XX
] = dipole
[i
][XX
];
903 muall
[i
][tel3
+YY
] = dipole
[i
][YY
];
904 muall
[i
][tel3
+ZZ
] = dipole
[i
][ZZ
];
907 for(m
=0; (m
<DIM
); m
++) {
908 M_av
[m
] += dipole
[i
][m
]; /* M per frame */
909 mu_mol
+= dipole
[i
][m
]*dipole
[i
][m
]; /* calc. mu for distribution */
911 mu_mol
= sqrt(mu_mol
);
913 mu_ave
+= mu_mol
; /* calc. the average mu */
915 /* Update the dipole distribution */
916 ibin
= (int)(ndipbin
*mu_mol
/mu_max
+ 0.5);
921 rvec2sprvec(dipole
[i
],dipsp
[i
]);
923 if (dipsp
[i
][YY
] > -M_PI
&& dipsp
[i
][YY
] < -0.5*M_PI
) {
924 if (dipsp
[i
][ZZ
] < 0.5 * M_PI
) {
929 }else if (dipsp
[i
][YY
] > -0.5*M_PI
&& dipsp
[i
][YY
] < 0.0*M_PI
) {
930 if (dipsp
[i
][ZZ
] < 0.5 * M_PI
) {
935 }else if (dipsp
[i
][YY
] > 0.0 && dipsp
[i
][YY
] < 0.5*M_PI
) {
936 if (dipsp
[i
][ZZ
] < 0.5 * M_PI
) {
941 }else if (dipsp
[i
][YY
] > 0.5*M_PI
&& dipsp
[i
][YY
] < M_PI
) {
942 if (dipsp
[i
][ZZ
] < 0.5 * M_PI
) {
949 fprintf(dip3d
,"set arrow %d from %f, %f, %f to %f, %f, %f lt %d # %d %d\n",
954 x
[ind0
][XX
]+dipole
[i
][XX
]/25,
955 x
[ind0
][YY
]+dipole
[i
][YY
]/25,
956 x
[ind0
][ZZ
]+dipole
[i
][ZZ
]/25,
959 } /* End loop of all molecules in frame */
962 fprintf(dip3d
,"set title \"t = %4.3f\"\n",t
);
963 fprintf(dip3d
,"set xrange [0.0:%4.2f]\n",box
[XX
][XX
]);
964 fprintf(dip3d
,"set yrange [0.0:%4.2f]\n",box
[YY
][YY
]);
965 fprintf(dip3d
,"set zrange [0.0:%4.2f]\n\n",box
[ZZ
][ZZ
]);
966 fprintf(dip3d
,"splot 'dummy.dat' using 1:2:3 w vec\n");
967 fprintf(dip3d
,"pause -1 'Hit return to continue'\n");
971 /* Compute square of total dipole */
972 for(m
=0; (m
<DIM
); m
++)
973 M_av2
[m
] = M_av
[m
]*M_av
[m
];
976 compute_avercos(gnx_tot
,dipole
,&dd
,dipaxis
,bPairs
);
977 rms_cos
= sqrt(sqr(dipaxis
[XX
]-0.5)+
978 sqr(dipaxis
[YY
]-0.5)+
979 sqr(dipaxis
[ZZ
]-0.5));
981 fprintf(caver
,"%10.3e %10.3e %10.3e %10.3e %10.3e %10.3e\n",
982 t
,dd
,rms_cos
,dipaxis
[XX
],dipaxis
[YY
],dipaxis
[ZZ
]);
984 fprintf(caver
,"%10.3e %10.3e %10.3e %10.3e %10.3e\n",
985 t
,rms_cos
,dipaxis
[XX
],dipaxis
[YY
],dipaxis
[ZZ
]);
989 do_gkr(gkrbin
,ncos
,gnx
,molindex
,mols
->index
,x
,dipole
,ePBC
,box
,
995 muall
[0][tel3
+XX
] = M_av
[XX
];
996 muall
[0][tel3
+YY
] = M_av
[YY
];
997 muall
[0][tel3
+ZZ
] = M_av
[ZZ
];
1000 /* Write to file the total dipole moment of the box, and its components
1003 if ((skip
== 0) || ((teller
% skip
) == 0))
1004 fprintf(outmtot
,"%10g %12.8e %12.8e %12.8e %12.8e\n",
1005 t
,M_av
[XX
],M_av
[YY
],M_av
[ZZ
],
1006 sqrt(M_av2
[XX
]+M_av2
[YY
]+M_av2
[ZZ
]));
1008 for(m
=0; (m
<DIM
); m
++) {
1011 M4
[m
] += sqr(M_av2
[m
]);
1013 /* Increment loop counter */
1016 /* Calculate for output the running averages */
1017 invtel
= 1.0/teller
;
1018 M2_ave
= (M2
[XX
]+M2
[YY
]+M2
[ZZ
])*invtel
;
1019 M_ave2
= invtel
*(invtel
*(M
[XX
]*M
[XX
] + M
[YY
]*M
[YY
] + M
[ZZ
]*M
[ZZ
]));
1020 M_diff
= M2_ave
- M_ave2
;
1022 /* Compute volume from box in traj, else we use the one from above */
1027 epsilon
= calc_eps(M_diff
,(vol_aver
/teller
),epsilonRF
,temp
);
1029 /* Calculate running average for dipole */
1031 mu_aver
= (mu_ave
/gnx_tot
)*invtel
;
1033 if ((skip
== 0) || ((teller
% skip
) == 0)) {
1034 /* Write to file < |M|^2 >, |< M >|^2. And the difference between
1035 * the two. Here M is sum mu_i. Further write the finite system
1036 * Kirkwood G factor and epsilon.
1038 fprintf(outaver
,"%10g %10.3e %10.3e %10.3e %10.3e\n",
1039 t
,M2_ave
,M_ave2
,M_diff
,M_ave2
/M2_ave
);
1043 gmx_stats_get_average(muframelsq
,&aver
);
1044 fprintf(adip
, "%10g %f \n", t
,aver
);
1047 printf("%f %f\n", norm(dipole[0]), norm(dipole[1]));
1049 if (!bMU
|| (mu_aver
!= -1)) {
1050 /* Finite system Kirkwood G-factor */
1051 Gk
= M_diff
/(gnx_tot
*mu_aver
*mu_aver
);
1052 /* Infinite system Kirkwood G-factor */
1053 if (epsilonRF
== 0.0)
1054 g_k
= ((2*epsilon
+1)*Gk
/(3*epsilon
));
1056 g_k
= ((2*epsilonRF
+epsilon
)*(2*epsilon
+1)*
1057 Gk
/(3*epsilon
*(2*epsilonRF
+1)));
1059 fprintf(outeps
,"%10g %10.3e %10.3e %10.3e\n",t
,epsilon
,Gk
,g_k
);
1063 fprintf(outeps
,"%10g %12.8e\n",t
,epsilon
);
1067 bCont
= read_mu_from_enx(fmu
,iVol
,iMu
,mu_t
,&volume
,&t
,nre
,fr
);
1069 bCont
= read_next_x(oenv
,status
,&t
,natom
,x
,box
);
1086 fprintf(dip3d
,"set xrange [0.0:%4.2f]\n",box
[XX
][XX
]);
1087 fprintf(dip3d
,"set yrange [0.0:%4.2f]\n",box
[YY
][YY
]);
1088 fprintf(dip3d
,"set zrange [0.0:%4.2f]\n\n",box
[ZZ
][ZZ
]);
1089 fprintf(dip3d
,"splot 'dummy.dat' using 1:2:3 w vec\n");
1090 fprintf(dip3d
,"pause -1 'Hit return to continue'\n");
1095 dump_slab_dipoles(slabfn
,idim
,nslices
,slab_dipoles
,box
,teller
,oenv
);
1096 sfree(slab_dipoles
);
1100 printf("Average volume over run is %g\n",vol_aver
);
1102 print_gkrbin(gkrfn
,gkrbin
,gnx
[0],teller
,vol_aver
,oenv
);
1103 print_cmap(cmap
,gkrbin
,nlevels
);
1105 /* Autocorrelation function */
1108 printf("Not enough frames for autocorrelation\n");
1111 dt
=(t1
- t0
)/(teller
-1);
1112 printf("t0 %g, t %g, teller %d\n", t0
,t
,teller
);
1117 do_autocorr(corf
,oenv
,"Autocorrelation Function of Total Dipole",
1118 teller
,1,muall
,dt
,mode
,TRUE
);
1120 do_autocorr(corf
,oenv
,"Dipole Autocorrelation Function",
1121 teller
,gnx_tot
,muall
,dt
,
1122 mode
,strcmp(corrtype
,"molsep"));
1126 real aver
,sigma
,error
,lsq
;
1128 gmx_stats_get_ase(mulsq
,&aver
,&sigma
,&error
);
1129 printf("\nDipole moment (Debye)\n");
1130 printf("---------------------\n");
1131 printf("Average = %8.4f Std. Dev. = %8.4f Error = %8.4f\n",
1136 for(m
=0; (m
<DIM
); m
++)
1137 gmx_stats_get_ase(mulsq
,&(a
[m
]),&(s
[m
]),&(e
[m
]));
1139 printf("\nQuadrupole moment (Debye-Ang)\n");
1140 printf("-----------------------------\n");
1141 printf("Averages = %8.4f %8.4f %8.4f\n",a
[XX
],a
[YY
],a
[ZZ
]);
1142 printf("Std. Dev. = %8.4f %8.4f %8.4f\n",s
[XX
],s
[YY
],s
[ZZ
]);
1143 printf("Error = %8.4f %8.4f %8.4f\n",e
[XX
],e
[YY
],e
[ZZ
]);
1147 printf("The following averages for the complete trajectory have been calculated:\n\n");
1148 printf(" Total < M_x > = %g Debye\n", M
[XX
]/teller
);
1149 printf(" Total < M_y > = %g Debye\n", M
[YY
]/teller
);
1150 printf(" Total < M_z > = %g Debye\n\n", M
[ZZ
]/teller
);
1152 printf(" Total < M_x^2 > = %g Debye^2\n", M2
[XX
]/teller
);
1153 printf(" Total < M_y^2 > = %g Debye^2\n", M2
[YY
]/teller
);
1154 printf(" Total < M_z^2 > = %g Debye^2\n\n", M2
[ZZ
]/teller
);
1156 printf(" Total < |M|^2 > = %g Debye^2\n", M2_ave
);
1157 printf(" Total |< M >|^2 = %g Debye^2\n\n", M_ave2
);
1159 printf(" < |M|^2 > - |< M >|^2 = %g Debye^2\n\n", M_diff
);
1161 if (!bMU
|| (mu_aver
!= -1)) {
1162 printf("Finite system Kirkwood g factor G_k = %g\n", Gk
);
1163 printf("Infinite system Kirkwood g factor g_k = %g\n\n", g_k
);
1165 printf("Epsilon = %g\n", epsilon
);
1168 /* Write to file the dipole moment distibution during the simulation.
1170 outdd
=xvgropen(dipdist
,"Dipole Moment Distribution","mu (Debye)","",oenv
);
1171 for(i
=0; (i
<ndipbin
); i
++)
1172 fprintf(outdd
,"%10g %10f\n",
1173 (i
*mu_max
)/ndipbin
,dipole_bin
[i
]/(double)teller
);
1178 done_gkrbin(&gkrbin
);
1181 void dipole_atom2molindex(int *n
,int *index
,t_block
*mols
)
1189 while(m
< mols
->nr
&& index
[i
] != mols
->index
[m
])
1192 gmx_fatal(FARGS
,"index[%d]=%d does not correspond to the first atom of a molecule",i
+1,index
[i
]+1);
1193 for(j
=mols
->index
[m
]; j
<mols
->index
[m
+1]; j
++) {
1194 if (i
>= *n
|| index
[i
] != j
)
1195 gmx_fatal(FARGS
,"The index group is not a set of whole molecules");
1198 /* Modify the index in place */
1201 printf("There are %d molecules in the selection\n",nmol
);
1205 int gmx_dipoles(int argc
,char *argv
[])
1207 const char *desc
[] = {
1208 "g_dipoles computes the total dipole plus fluctuations of a simulation",
1209 "system. From this you can compute e.g. the dielectric constant for",
1210 "low dielectric media.",
1211 "For molecules with a net charge, the net charge is subtracted at",
1212 "center of mass of the molecule.[PAR]",
1213 "The file Mtot.xvg contains the total dipole moment of a frame, the",
1214 "components as well as the norm of the vector.",
1215 "The file aver.xvg contains < |Mu|^2 > and |< Mu >|^2 during the",
1217 "The file dipdist.xvg contains the distribution of dipole moments during",
1219 "The mu_max is used as the highest value in the distribution graph.[PAR]",
1220 "Furthermore the dipole autocorrelation function will be computed when",
1221 "option -corr is used. The output file name is given with the [TT]-c[tt]",
1223 "The correlation functions can be averaged over all molecules",
1224 "([TT]mol[tt]), plotted per molecule seperately ([TT]molsep[tt])",
1225 "or it can be computed over the total dipole moment of the simulation box",
1226 "([TT]total[tt]).[PAR]",
1227 "Option [TT]-g[tt] produces a plot of the distance dependent Kirkwood",
1228 "G-factor, as well as the average cosine of the angle between the dipoles",
1229 "as a function of the distance. The plot also includes gOO and hOO",
1230 "according to Nymand & Linse, JCP 112 (2000) pp 6386-6395. In the same plot",
1231 "we also include the energy per scale computed by taking the inner product of",
1232 "the dipoles divided by the distance to the third power.[PAR]",
1235 "g_dipoles -corr mol -P1 -o dip_sqr -mu 2.273 -mumax 5.0 -nofft[PAR]",
1236 "This will calculate the autocorrelation function of the molecular",
1237 "dipoles using a first order Legendre polynomial of the angle of the",
1238 "dipole vector and itself a time t later. For this calculation 1001",
1239 "frames will be used. Further the dielectric constant will be calculated",
1240 "using an epsilonRF of infinity (default), temperature of 300 K (default) and",
1241 "an average dipole moment of the molecule of 2.273 (SPC). For the",
1242 "distribution function a maximum of 5.0 will be used."
1244 real mu_max
=5, mu_aver
=-1,rcmax
=0;
1245 real epsilonRF
=0.0, temp
=300;
1246 bool bAverCorr
=FALSE
,bMolCorr
=FALSE
,bPairs
=TRUE
,bPhi
=FALSE
;
1247 const char *corrtype
[]={NULL
, "none", "mol", "molsep", "total", NULL
};
1248 const char *axtitle
="Z";
1249 int nslices
= 10; /* nr of slices defined */
1250 int skip
=0,nFA
=0,nFB
=0,ncos
=1;
1251 int nlevels
=20,ndegrees
=90;
1254 { "-mu", FALSE
, etREAL
, {&mu_aver
},
1255 "dipole of a single molecule (in Debye)" },
1256 { "-mumax", FALSE
, etREAL
, {&mu_max
},
1257 "max dipole in Debye (for histrogram)" },
1258 { "-epsilonRF",FALSE
, etREAL
, {&epsilonRF
},
1259 "epsilon of the reaction field used during the simulation, needed for dieclectric constant calculation. WARNING: 0.0 means infinity (default)" },
1260 { "-skip", FALSE
, etINT
, {&skip
},
1261 "Skip steps in the output (but not in the computations)" },
1262 { "-temp", FALSE
, etREAL
, {&temp
},
1263 "Average temperature of the simulation (needed for dielectric constant calculation)" },
1264 { "-corr", FALSE
, etENUM
, {corrtype
},
1265 "Correlation function to calculate" },
1266 { "-pairs", FALSE
, etBOOL
, {&bPairs
},
1267 "Calculate |cos theta| between all pairs of molecules. May be slow" },
1268 { "-ncos", FALSE
, etINT
, {&ncos
},
1269 "Must be 1 or 2. Determines whether the <cos> is computed between all mole cules in one group, or between molecules in two different groups. This turns on the -gkr flag." },
1270 { "-axis", FALSE
, etSTR
, {&axtitle
},
1271 "Take the normal on the computational box in direction X, Y or Z." },
1272 { "-sl", FALSE
, etINT
, {&nslices
},
1273 "Divide the box in #nr slices." },
1274 { "-gkratom", FALSE
, etINT
, {&nFA
},
1275 "Use the n-th atom of a molecule (starting from 1) to calculate the distance between molecules rather than the center of charge (when 0) in the calculation of distance dependent Kirkwood factors" },
1276 { "-gkratom2", FALSE
, etINT
, {&nFB
},
1277 "Same as previous option in case ncos = 2, i.e. dipole interaction between two groups of molecules" },
1278 { "-rcmax", FALSE
, etREAL
, {&rcmax
},
1279 "Maximum distance to use in the dipole orientation distribution (with ncos == 2). If zero, a criterium based on the box length will be used." },
1280 { "-phi", FALSE
, etBOOL
, {&bPhi
},
1281 "Plot the 'torsion angle' defined as the rotation of the two dipole vectors around the distance vector between the two molecules in the xpm file from the -cmap option. By default the cosine of the angle between the dipoles is plotted." },
1282 { "-nlevels", FALSE
, etINT
, {&nlevels
},
1283 "Number of colors in the cmap output" },
1284 { "-ndegrees", FALSE
, etINT
, {&ndegrees
},
1285 "Number of divisions on the y-axis in the camp output (for 180 degrees)" }
1290 char **grpname
=NULL
;
1291 bool bCorr
,bQuad
,bGkr
,bMU
,bSlab
;
1293 { efEDR
, "-en", NULL
, ffOPTRD
},
1294 { efTRX
, "-f", NULL
, ffREAD
},
1295 { efTPX
, NULL
, NULL
, ffREAD
},
1296 { efNDX
, NULL
, NULL
, ffOPTRD
},
1297 { efXVG
, "-o", "Mtot", ffWRITE
},
1298 { efXVG
, "-eps", "epsilon", ffWRITE
},
1299 { efXVG
, "-a", "aver", ffWRITE
},
1300 { efXVG
, "-d", "dipdist", ffWRITE
},
1301 { efXVG
, "-c", "dipcorr", ffOPTWR
},
1302 { efXVG
, "-g", "gkr", ffOPTWR
},
1303 { efXVG
, "-adip","adip", ffOPTWR
},
1304 { efXVG
, "-dip3d", "dip3d", ffOPTWR
},
1305 { efXVG
, "-cos", "cosaver", ffOPTWR
},
1306 { efXPM
, "-cmap","cmap", ffOPTWR
},
1307 { efXVG
, "-q", "quadrupole", ffOPTWR
},
1308 { efXVG
, "-slab","slab", ffOPTWR
}
1310 #define NFILE asize(fnm)
1318 CopyRight(stderr
,argv
[0]);
1320 ppa
= add_acf_pargs(&npargs
,pa
);
1321 parse_common_args(&argc
,argv
,PCA_CAN_TIME
| PCA_CAN_VIEW
| PCA_BE_NICE
,
1322 NFILE
,fnm
,npargs
,ppa
,asize(desc
),desc
,0,NULL
,&oenv
);
1324 printf("Using %g as mu_max and %g as the dipole moment.\n",
1326 if (epsilonRF
== 0.0)
1327 printf("WARNING: EpsilonRF = 0.0, this really means EpsilonRF = infinity\n");
1329 bMU
= opt2bSet("-en",NFILE
,fnm
);
1330 bQuad
= opt2bSet("-q",NFILE
,fnm
);
1331 bGkr
= opt2bSet("-g",NFILE
,fnm
);
1332 if (opt2parg_bSet("-ncos",asize(pa
),pa
)) {
1333 if ((ncos
!= 1) && (ncos
!= 2))
1334 gmx_fatal(FARGS
,"ncos has to be either 1 or 2");
1337 bSlab
= (opt2bSet("-slab",NFILE
,fnm
) || opt2parg_bSet("-sl",asize(pa
),pa
) ||
1338 opt2parg_bSet("-axis",asize(pa
),pa
));
1342 printf("WARNING: Can not determine quadrupoles from energy file\n");
1346 printf("WARNING: Can not determine Gk(r) from energy file\n");
1351 printf("WARNING: Can not calculate Gk and gk, since you did\n"
1352 " not enter a valid dipole for the molecules\n");
1356 ePBC
= read_tpx_top(ftp2fn(efTPX
,NFILE
,fnm
),NULL
,box
,
1357 &natoms
,NULL
,NULL
,NULL
,top
);
1361 snew(grpindex
,ncos
);
1362 get_index(&top
->atoms
,ftp2fn_null(efNDX
,NFILE
,fnm
),
1363 ncos
,gnx
,grpindex
,grpname
);
1364 for(k
=0; (k
<ncos
); k
++) {
1365 dipole_atom2molindex(&gnx
[k
],grpindex
[k
],&(top
->mols
));
1366 neutralize_mols(gnx
[k
],grpindex
[k
],&(top
->mols
),top
->atoms
.atom
);
1370 do_dip(top
,ePBC
,det(box
),ftp2fn(efTRX
,NFILE
,fnm
),
1371 opt2fn("-o",NFILE
,fnm
),opt2fn("-eps",NFILE
,fnm
),
1372 opt2fn("-a",NFILE
,fnm
),opt2fn("-d",NFILE
,fnm
),
1373 opt2fn_null("-cos",NFILE
,fnm
),
1374 opt2fn_null("-dip3d",NFILE
,fnm
),opt2fn_null("-adip",NFILE
,fnm
),
1376 opt2fn("-c",NFILE
,fnm
),
1377 bGkr
, opt2fn("-g",NFILE
,fnm
),
1378 bPhi
, &nlevels
, ndegrees
,
1380 opt2fn("-cmap",NFILE
,fnm
),rcmax
,
1381 bQuad
, opt2fn("-q",NFILE
,fnm
),
1382 bMU
, opt2fn("-en",NFILE
,fnm
),
1383 gnx
,grpindex
,mu_max
,mu_aver
,epsilonRF
,temp
,nFF
,skip
,
1384 bSlab
,nslices
,axtitle
,opt2fn("-slab",NFILE
,fnm
),oenv
);
1386 do_view(oenv
,opt2fn("-o",NFILE
,fnm
),"-autoscale xy -nxy");
1387 do_view(oenv
,opt2fn("-eps",NFILE
,fnm
),"-autoscale xy -nxy");
1388 do_view(oenv
,opt2fn("-a",NFILE
,fnm
),"-autoscale xy -nxy");
1389 do_view(oenv
,opt2fn("-d",NFILE
,fnm
),"-autoscale xy");
1390 do_view(oenv
,opt2fn("-c",NFILE
,fnm
),"-autoscale xy");