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"
63 #define e2d(x) ENM2DEBYE*(x)
64 #define EANG2CM E_CHARGE*1.0e-10 /* e Angstrom to Coulomb meter */
65 #define CM2D SPEED_OF_LIGHT*1.0e+24 /* Coulomb meter to Debye */
77 static t_gkrbin
*mk_gkrbin(real radius
,real rcmax
,bool bPhi
,int ndegrees
)
85 if ((ptr
= getenv("GKRWIDTH")) != NULL
) {
88 sscanf(ptr
,"%lf",&bw
);
92 gb
->spacing
= 0.01; /* nm */
93 gb
->nelem
= 1 + radius
/gb
->spacing
;
97 gb
->nx
= 1 + rcmax
/gb
->spacing
;
99 snew(gb
->elem
,gb
->nelem
);
100 snew(gb
->count
,gb
->nelem
);
102 snew(gb
->cmap
,gb
->nx
);
103 gb
->ny
= max(2,ndegrees
);
104 for(i
=0; (i
<gb
->nx
); i
++)
105 snew(gb
->cmap
[i
],gb
->ny
);
111 static void done_gkrbin(t_gkrbin
**gb
)
119 static void add2gkr(t_gkrbin
*gb
,real r
,real cosa
,real phi
)
121 int cy
,index
= gmx_nint(r
/gb
->spacing
);
124 if (index
< gb
->nelem
) {
125 gb
->elem
[index
] += cosa
;
128 if (index
< gb
->nx
) {
131 cy
= (M_PI
+phi
)*gb
->ny
/(2*M_PI
);
133 cy
= (alpha
*gb
->ny
)/M_PI
;/*((1+cosa)*0.5*(gb->ny));*/
134 cy
= min(gb
->ny
-1,max(0,cy
));
136 fprintf(debug
,"CY: %10f %5d\n",alpha
,cy
);
137 gb
->cmap
[index
][cy
] += 1;
141 static void rvec2sprvec(rvec dipcart
,rvec dipsp
)
144 dipsp
[0] = sqrt(dipcart
[XX
]*dipcart
[XX
]+dipcart
[YY
]*dipcart
[YY
]+dipcart
[ZZ
]*dipcart
[ZZ
]); /* R */
145 dipsp
[1] = atan2(dipcart
[YY
],dipcart
[XX
]); /* Theta */
146 dipsp
[2] = atan2(sqrt(dipcart
[XX
]*dipcart
[XX
]+dipcart
[YY
]*dipcart
[YY
]),dipcart
[ZZ
]); /* Phi */
151 void do_gkr(t_gkrbin
*gb
,int ncos
,int *ngrp
,int *molindex
[],
152 int mindex
[],rvec x
[],rvec mu
[],
153 int ePBC
,matrix box
,t_atom
*atom
,int *nAtom
)
155 static rvec
*xcm
[2] = { NULL
, NULL
};
156 int gi
,gj
,j0
,j1
,i
,j
,k
,n
,index
,grp0
,grp1
;
157 real qtot
,q
,r2
,cosa
,rr
,phi
;
161 for(n
=0; (n
<ncos
); n
++) {
163 snew(xcm
[n
],ngrp
[n
]);
164 for(i
=0; (i
<ngrp
[n
]); i
++) {
165 /* Calculate center of mass of molecule */
170 copy_rvec(x
[j0
+nAtom
[n
]-1],xcm
[n
][i
]);
173 clear_rvec(xcm
[n
][i
]);
175 for(j
=j0
; j
<j1
; j
++) {
179 xcm
[n
][i
][k
] += q
*x
[j
][k
];
181 svmul(1/qtot
,xcm
[n
][i
],xcm
[n
][i
]);
185 set_pbc(&pbc
,ePBC
,box
);
188 for(i
=0; i
<ngrp
[grp0
]; i
++) {
189 gi
= molindex
[grp0
][i
];
190 j0
= (ncos
== 2) ? 0 : i
+1;
191 for(j
=j0
; j
<ngrp
[grp1
]; j
++) {
192 gj
= molindex
[grp1
][j
];
193 if ((iprod(mu
[gi
],mu
[gi
]) > 0) && (iprod(mu
[gj
],mu
[gj
]) > 0)) {
194 /* Compute distance between molecules including PBC */
195 pbc_dx(&pbc
,xcm
[grp0
][i
],xcm
[grp1
][j
],dx
);
200 rvec r_ij
,r_kj
,r_kl
,mm
,nn
;
204 copy_rvec(xcm
[grp0
][i
],xj
);
205 copy_rvec(xcm
[grp1
][j
],xk
);
206 rvec_add(xj
,mu
[gi
],xi
);
207 rvec_add(xk
,mu
[gj
],xl
);
208 phi
= dih_angle(xi
,xj
,xk
,xl
,&pbc
,
209 r_ij
,r_kj
,r_kl
,mm
,nn
, /* out */
210 &cosa
,&sign
,&t1
,&t2
,&t3
);
213 cosa
= cos_angle(mu
[gi
],mu
[gj
]);
216 if (debug
|| (cosa
!= cosa
)) {
217 fprintf(debug
? debug
: stderr
,
218 "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",
219 gi
,mu
[gi
][XX
],mu
[gi
][YY
],mu
[gi
][ZZ
],norm(mu
[gi
]),
220 gj
,mu
[gj
][XX
],mu
[gj
][YY
],mu
[gj
][ZZ
],norm(mu
[gj
]),
224 add2gkr(gb
,rr
,cosa
,phi
);
230 static real
normalize_cmap(t_gkrbin
*gb
)
236 for(i
=0; (i
<gb
->nx
); i
++) {
237 vol
= 4*M_PI
*sqr(gb
->spacing
*i
)*gb
->spacing
;
238 for(j
=0; (j
<gb
->ny
); j
++) {
239 gb
->cmap
[i
][j
] /= vol
;
240 hi
= max(hi
,gb
->cmap
[i
][j
]);
244 gmx_fatal(FARGS
,"No data in the cmap");
248 static void print_cmap(const char *cmap
,t_gkrbin
*gb
,int *nlevels
)
255 t_rgb rlo
= { 1, 1, 1 };
256 t_rgb rhi
= { 0, 0, 0 };
258 hi
= normalize_cmap(gb
);
259 snew(xaxis
,gb
->nx
+1);
260 for(i
=0; (i
<gb
->nx
+1); i
++)
261 xaxis
[i
] = i
*gb
->spacing
;
263 for(j
=0; (j
<gb
->ny
); j
++) {
265 yaxis
[j
] = (360.0*j
)/(gb
->ny
-1.0)-180;
267 yaxis
[j
] = (180.0*j
)/(gb
->ny
-1.0);
268 /*2.0*j/(gb->ny-1.0)-1.0;*/
270 out
= fopen(cmap
,"w");
272 "Dipole Orientation Distribution","Fraction","r (nm)",
273 gb
->bPhi
? "Phi" : "Alpha",
274 gb
->nx
,gb
->ny
,xaxis
,yaxis
,
275 gb
->cmap
,0,hi
,rlo
,rhi
,nlevels
);
281 static void print_gkrbin(const char *fn
,t_gkrbin
*gb
,
282 int ngrp
,int nframes
,real volume
,
283 const output_env_t oenv
)
285 /* We compute Gk(r), gOO and hOO according to
286 * Nymand & Linse, JCP 112 (2000) pp 6386-6395.
287 * In this implementation the angle between dipoles is stored
288 * rather than their inner product. This allows to take polarizible
289 * models into account. The RDF is calculated as well, almost for free!
292 char *leg
[] = { "G\\sk\\N(r)", "< cos >", "h\\sOO\\N", "g\\sOO\\N", "Energy" };
294 real x0
,x1
,ggg
,Gkr
,vol_s
,rho
,gOO
,hOO
,cosav
,ener
;
297 fp
=xvgropen(fn
,"Distance dependent Gk","r (nm)","G\\sk\\N(r)",oenv
);
298 xvgr_legend(fp
,asize(leg
),leg
,oenv
);
300 Gkr
= 1; /* Self-dipole inproduct = 1 */
304 fprintf(debug
,"Number density is %g molecules / nm^3\n",rho
);
305 fprintf(debug
,"ngrp = %d, nframes = %d\n",ngrp
,nframes
);
309 while(last
>1 && gb
->elem
[last
-1]==0)
312 /* Divide by dipole squared, by number of frames, by number of origins.
313 * Multiply by 2 because we only take half the matrix of interactions
316 fac
= 2.0/((double) ngrp
* (double) nframes
);
319 for(i
=0; i
<last
; i
++) {
320 /* Centre of the coordinate in the spherical layer */
323 /* Volume of the layer */
324 vol_s
= (4.0/3.0)*M_PI
*(x1
*x1
*x1
-x0
*x0
*x0
);
327 gOO
= gb
->count
[i
]*fac
/(rho
*vol_s
);
329 /* Dipole correlation hOO, normalized by the relative number density, like
330 * in a Radial distribution function.
332 ggg
= gb
->elem
[i
]*fac
;
333 hOO
= 3.0*ggg
/(rho
*vol_s
);
336 cosav
= gb
->elem
[i
]/gb
->count
[i
];
339 ener
= -0.5*cosav
*ONE_4PI_EPS0
/(x1
*x1
*x1
);
341 fprintf(fp
,"%10.5e %12.5e %12.5e %12.5e %12.5e %12.5e\n",
342 x1
,Gkr
,cosav
,hOO
,gOO
,ener
);
350 bool read_mu_from_enx(ener_file_t fmu
,int Vol
,ivec iMu
,rvec mu
,real
*vol
,
351 real
*t
, int nre
,t_enxframe
*fr
)
357 bCont
= do_enx(fmu
,fr
);
359 fprintf(stderr
,"Something strange: expected %d entries in energy file at step %s\n(time %g) but found %d entries\n",
360 nre
,gmx_step_str(fr
->step
,buf
),fr
->t
,fr
->nre
);
363 if (Vol
!= -1) /* we've got Volume in the energy file */
364 *vol
= fr
->ener
[Vol
].e
;
365 for (i
=0; i
<DIM
; i
++)
366 mu
[i
] = fr
->ener
[iMu
[i
]].e
;
373 static void neutralize_mols(int n
,int *index
,t_block
*mols
,t_atom
*atom
)
376 int ncharged
,m
,a0
,a1
,a
;
380 a0
= mols
->index
[index
[m
]];
381 a1
= mols
->index
[index
[m
]+1];
384 for(a
=a0
; a
<a1
; a
++) {
388 /* This check is only for the count print */
389 if (fabs(qtot
) > 0.01)
392 /* Remove the net charge at the center of mass */
394 atom
[a
].q
-= qtot
*atom
[a
].m
/mtot
;
399 printf("There are %d charged molecules in the selection,\n"
400 "will subtract their charge at their center of mass\n",ncharged
);
403 static void mol_dip(int k0
,int k1
,rvec x
[],t_atom atom
[],rvec mu
)
409 for(k
=k0
; (k
<k1
); k
++) {
411 for(m
=0; (m
<DIM
); m
++)
416 static void mol_quad(int k0
,int k1
,rvec x
[],t_atom atom
[],rvec quad
)
419 real q
,r2
,mass
,masstot
;
420 rvec com
; /* center of mass */
421 rvec r
; /* distance of atoms to center of mass */
424 double dd
[DIM
],**ev
,tmp
;
428 for(i
=0; (i
<DIM
); i
++) {
434 /* Compute center of mass */
437 for(k
=k0
; (k
<k1
); k
++) {
440 for(i
=0; (i
<DIM
); i
++)
441 com
[i
] += mass
*x
[k
][i
];
443 svmul((1.0/masstot
),com
,com
);
445 /* We want traceless quadrupole moments, so let us calculate the complete
446 * quadrupole moment tensor and diagonalize this tensor to get
447 * the individual components on the diagonal.
450 #define delta(a,b) (( a == b ) ? 1.0 : 0.0)
452 for(m
=0; (m
<DIM
); m
++)
453 for(n
=0; (n
<DIM
); n
++)
455 for(k
=k0
; (k
<k1
); k
++) { /* loop over atoms in a molecule */
456 q
= (atom
[k
].q
)*100.0;
457 rvec_sub(x
[k
],com
,r
);
459 for(m
=0; (m
<DIM
); m
++)
460 for(n
=0; (n
<DIM
); n
++)
461 inten
[m
][n
] += 0.5*q
*(3.0*r
[m
]*r
[n
] - r2
*delta(m
,n
))*EANG2CM
*CM2D
;
464 for(i
=0; (i
<DIM
); i
++)
465 fprintf(debug
,"Q[%d] = %8.3f %8.3f %8.3f\n",
466 i
,inten
[i
][XX
],inten
[i
][YY
],inten
[i
][ZZ
]);
468 /* We've got the quadrupole tensor, now diagonalize the sucker */
469 jacobi(inten
,3,dd
,ev
,&niter
);
472 for(i
=0; (i
<DIM
); i
++)
473 fprintf(debug
,"ev[%d] = %8.3f %8.3f %8.3f\n",
474 i
,ev
[i
][XX
],ev
[i
][YY
],ev
[i
][ZZ
]);
475 for(i
=0; (i
<DIM
); i
++)
476 fprintf(debug
,"Q'[%d] = %8.3f %8.3f %8.3f\n",
477 i
,inten
[i
][XX
],inten
[i
][YY
],inten
[i
][ZZ
]);
479 /* Sort the eigenvalues, for water we know that the order is as follows:
483 * At the moment I have no idea how this will work out for other molecules...
487 if (dd[i+1] > dd[i]) { \
496 for(m
=0; (m
<DIM
); m
++) {
497 quad
[0]=dd
[2]; /* yy */
498 quad
[1]=dd
[0]; /* zz */
499 quad
[2]=dd
[1]; /* xx */
503 pr_rvec(debug
,0,"Quadrupole",quad
,DIM
,TRUE
);
506 for(i
=0; (i
<DIM
); i
++) {
515 * Calculates epsilon according to M. Neumann, Mol. Phys. 50, 841 (1983)
517 real
calc_eps(double M_diff
,double volume
,double epsRF
,double temp
)
519 double eps
,A
,teller
,noemer
;
520 double eps_0
=8.854187817e-12; /* epsilon_0 in C^2 J^-1 m^-1 */
521 double fac
=1.112650021e-59; /* converts Debye^2 to C^2 m^2 */
523 A
= M_diff
*fac
/(3*eps_0
*volume
*NANO
*NANO
*NANO
*BOLTZMANN
*temp
);
529 teller
= 1 + (A
*2*epsRF
/(2*epsRF
+1));
530 noemer
= 1 - (A
/(2*epsRF
+1));
532 eps
= teller
/ noemer
;
537 static void update_slab_dipoles(int k0
,int k1
,rvec x
[],rvec mu
,
538 int idim
,int nslice
,rvec slab_dipole
[],
544 for(k
=k0
; (k
<k1
); k
++)
547 k
= ((int)(xdim
*nslice
/box
[idim
][idim
] + nslice
)) % nslice
;
548 rvec_inc(slab_dipole
[k
],mu
);
551 static void dump_slab_dipoles(const char *fn
,int idim
,int nslice
,
552 rvec slab_dipole
[], matrix box
,int nframes
,
553 const output_env_t oenv
)
560 "\\f{12}m\\f{4}\\sX\\N",
561 "\\f{12}m\\f{4}\\sY\\N",
562 "\\f{12}m\\f{4}\\sZ\\N",
563 "\\f{12}m\\f{4}\\stot\\N"
566 sprintf(buf
,"Box-%c (nm)",'X'+idim
);
567 fp
= xvgropen(fn
,"Average dipole moment per slab",buf
,"\\f{12}m\\f{4} (D)",
569 xvgr_legend(fp
,DIM
,leg_dim
,oenv
);
570 for(i
=0; (i
<nslice
); i
++) {
571 mutot
= norm(slab_dipole
[i
])/nframes
;
572 fprintf(fp
,"%10.3f %10.3f %10.3f %10.3f %10.3f\n",
573 ((i
+0.5)*box
[idim
][idim
])/nslice
,
574 slab_dipole
[i
][XX
]/nframes
,
575 slab_dipole
[i
][YY
]/nframes
,
576 slab_dipole
[i
][ZZ
]/nframes
,
580 do_view(oenv
,fn
,"-autoscale xy -nxy");
583 static void compute_avercos(int n
,rvec dip
[],real
*dd
,rvec axis
,bool bPairs
)
586 double dc
,dc1
,d
,n5
,ddc1
,ddc2
,ddc3
;
587 rvec xxx
= { 1, 0, 0 };
588 rvec yyy
= { 0, 1, 0 };
589 rvec zzz
= { 0, 0, 1 };
592 ddc1
= ddc2
= ddc3
= 0;
593 for(i
=k
=0; (i
<n
); i
++) {
594 ddc1
+= fabs(cos_angle(dip
[i
],xxx
));
595 ddc2
+= fabs(cos_angle(dip
[i
],yyy
));
596 ddc3
+= fabs(cos_angle(dip
[i
],zzz
));
598 for(j
=i
+1; (j
<n
); j
++,k
++) {
599 dc
= cos_angle(dip
[i
],dip
[j
]);
609 static void do_dip(t_topology
*top
,int ePBC
,real volume
,
611 const char *out_mtot
,const char *out_eps
,
612 const char *out_aver
, const char *dipdist
,
613 const char *cosaver
, const char *fndip3d
,
614 const char *fnadip
, bool bPairs
,
615 const char *corrtype
,const char *corf
,
616 bool bGkr
, const char *gkrfn
,
617 bool bPhi
, int *nlevels
, int ndegrees
,
619 const char *cmap
, real rcmax
,
620 bool bQuad
, const char *quadfn
,
621 bool bMU
, const char *mufn
,
622 int *gnx
, int *molindex
[],
623 real mu_max
, real mu_aver
,
624 real epsilonRF
,real temp
,
625 int *gkatom
, int skip
,
626 bool bSlab
, int nslices
,
627 const char *axtitle
, const char *slabfn
,
628 const output_env_t oenv
)
636 #define NLEGMTOT asize(leg_mtot)
642 #define NLEGEPS asize(leg_eps)
646 "< |M|\\S2\\N > - < |M| >\\S2\\N",
647 "< |M| >\\S2\\N / < |M|\\S2\\N >"
649 #define NLEGAVER asize(leg_aver)
650 char *leg_cosaver
[] = {
651 "\\f{4}<|cos\\f{12}q\\f{4}\\sij\\N|>",
653 "\\f{4}<|cos\\f{12}q\\f{4}\\siX\\N|>",
654 "\\f{4}<|cos\\f{12}q\\f{4}\\siY\\N|>",
655 "\\f{4}<|cos\\f{12}q\\f{4}\\siZ\\N|>"
657 #define NLEGCOSAVER asize(leg_cosaver)
663 #define NLEGADIP asize(leg_adip)
665 FILE *outdd
,*outmtot
,*outaver
,*outeps
,*caver
=NULL
;
666 FILE *dip3d
=NULL
,*adip
=NULL
;
667 rvec
*x
,*dipole
=NULL
,mu_t
,quad
,*dipsp
=NULL
;
668 t_gkrbin
*gkrbin
= NULL
;
669 gmx_enxnm_t
*enm
=NULL
;
671 int nframes
=1000,nre
,timecheck
=0,ncolour
=0;
672 ener_file_t fmu
=NULL
;
673 int i
,j
,k
,n
,m
,natom
=0,nmol
,status
,gnx_tot
,teller
,tel3
;
674 int *dipole_bin
,ndipbin
,ibin
,iVol
,step
,idim
=-1;
677 real rcut
=0,t
,t0
,t1
,dt
,lambda
,dd
,rms_cos
;
680 bool bCorr
,bTotal
,bCont
;
681 double M_diff
=0,epsilon
,invtel
,vol_aver
;
682 double mu_ave
,mu_mol
,M2_ave
=0,M_ave2
=0,M_av
[DIM
],M_av2
[DIM
];
683 double M
[3],M2
[3],M4
[3],Gk
=0,g_k
=0;
684 gmx_stats_t Mx
,My
,Mz
,Msq
,Vol
,*Qlsq
,mulsq
,muframelsq
=NULL
;
687 rvec
*slab_dipoles
=NULL
;
700 fmu
= open_enx(mufn
,"r");
701 do_enxnms(fmu
,&nre
,&enm
);
703 /* Determine the indexes of the energy grps we need */
704 for (i
=0; (i
<nre
); i
++) {
705 if (strstr(enm
[i
].name
,"Volume"))
707 else if (strstr(enm
[i
].name
,"Mu-X"))
709 else if (strstr(enm
[i
].name
,"Mu-Y"))
711 else if (strstr(enm
[i
].name
,"Mu-Z"))
716 atom
= top
->atoms
.atom
;
721 printf("Using Volume from topology: %g nm^3\n",volume
);
723 /* Correlation stuff */
724 bCorr
= (corrtype
[0] != 'n');
725 bTotal
= (corrtype
[0] == 't');
729 snew(muall
[0],nframes
*DIM
);
733 for(i
=0; (i
<gnx
[0]); i
++)
734 snew(muall
[i
],nframes
*DIM
);
738 /* Allocate array which contains for every molecule in a frame the
742 snew(dipole
,gnx_tot
);
746 for(i
=0; (i
<DIM
); i
++)
747 Qlsq
[i
] = gmx_stats_init();
748 mulsq
= gmx_stats_init();
750 /* Open all the files */
751 outmtot
= xvgropen(out_mtot
,
752 "Total dipole moment of the simulation box vs. time",
753 "Time (ps)","Total Dipole Moment (Debye)",oenv
);
754 outeps
= xvgropen(out_eps
,"Epsilon and Kirkwood factors",
755 "Time (ps)","",oenv
);
756 outaver
= xvgropen(out_aver
,"Total dipole moment",
757 "Time (ps)","D",oenv
);
759 idim
= axtitle
[0] - 'X';
760 if ((idim
< 0) || (idim
>= DIM
))
761 idim
= axtitle
[0] - 'x';
762 if ((idim
< 0) || (idim
>= DIM
))
766 fprintf(stderr
,"axtitle = %s, nslices = %d, idim = %d\n",
767 axtitle
,nslices
,idim
);
769 snew(slab_dipoles
,nslices
);
770 fprintf(stderr
,"Doing slab analysis\n");
775 adip
= xvgropen(fnadip
, "Average molecular dipole","Dipole (D)","",oenv
);
776 xvgr_legend(adip
,NLEGADIP
,leg_adip
, oenv
);
780 caver
= xvgropen(cosaver
,bPairs
? "Average pair orientation" :
781 "Average absolute dipole orientation","Time (ps)","",oenv
);
782 xvgr_legend(caver
,NLEGCOSAVER
,bPairs
? leg_cosaver
: &(leg_cosaver
[1]),
789 /* we need a dummy file for gnuplot */
790 dip3d
= (FILE *)ffopen("dummy.dat","w");
791 fprintf(dip3d
,"%f %f %f", 0.0,0.0,0.0);
794 dip3d
= (FILE *)ffopen(fndip3d
,"w");
795 fprintf(dip3d
,"# This file was created by %s\n",Program());
796 fprintf(dip3d
,"# which is part of G R O M A C S:\n");
797 fprintf(dip3d
,"#\n");
800 /* Write legends to all the files */
801 xvgr_legend(outmtot
,NLEGMTOT
,leg_mtot
,oenv
);
802 xvgr_legend(outaver
,NLEGAVER
,leg_aver
,oenv
);
804 if (bMU
&& (mu_aver
== -1))
805 xvgr_legend(outeps
,NLEGEPS
-2,leg_eps
,oenv
);
807 xvgr_legend(outeps
,NLEGEPS
,leg_eps
,oenv
);
812 /* Read the first frame from energy or traj file */
815 bCont
= read_mu_from_enx(fmu
,iVol
,iMu
,mu_t
,&volume
,&t
,nre
,fr
);
817 timecheck
=check_times(t
);
820 if ((teller
% 10) == 0)
821 fprintf(stderr
,"\r Skipping Frame %6d, time: %8.3f", teller
, t
);
824 printf("End of %s reached\n",mufn
);
827 } while (bCont
&& (timecheck
< 0));
829 natom
= read_first_x(oenv
,&status
,fn
,&t
,&x
,box
);
831 /* Calculate spacing for dipole bin (simple histogram) */
832 ndipbin
= 1+(mu_max
/0.01);
833 snew(dipole_bin
, ndipbin
);
836 for(m
=0; (m
<DIM
); m
++) {
837 M
[m
] = M2
[m
] = M4
[m
] = 0.0;
841 /* Use 0.7 iso 0.5 to account for pressure scaling */
842 /* rcut = 0.7*sqrt(max_cutoff2(box)); */
843 rcut
= 0.7*sqrt(sqr(box
[XX
][XX
])+sqr(box
[YY
][YY
])+sqr(box
[ZZ
][ZZ
]));
845 gkrbin
= mk_gkrbin(rcut
,rcmax
,bPhi
,ndegrees
);
848 /* Start while loop over frames */
852 if (bCorr
&& (teller
>= nframes
)) {
855 srenew(muall
[0],nframes
*DIM
);
858 for(i
=0; (i
<gnx_tot
); i
++)
859 srenew(muall
[i
],nframes
*DIM
);
865 /* Copy rvec into double precision local variable */
866 for(m
=0; (m
<DIM
); m
++)
871 for(m
=0; (m
<DIM
); m
++) {
875 rm_pbc(&(top
->idef
),ePBC
,natom
,box
,x
,x
);
877 muframelsq
= gmx_stats_init();
878 /* Begin loop of all molecules in frame */
879 for(n
=0; (n
<ncos
); n
++) {
880 for(i
=0; (i
<gnx
[n
]); i
++) {
883 ind0
= mols
->index
[molindex
[n
][i
]];
884 ind1
= mols
->index
[molindex
[n
][i
]+1];
886 mol_dip(ind0
,ind1
,x
,atom
,dipole
[i
]);
887 gmx_stats_add_point(mulsq
,0,norm(dipole
[i
]),0,0);
888 gmx_stats_add_point(muframelsq
,0,norm(dipole
[i
]),0,0);
890 update_slab_dipoles(ind0
,ind1
,x
,
891 dipole
[i
],idim
,nslices
,slab_dipoles
,box
);
893 mol_quad(ind0
,ind1
,x
,atom
,quad
);
894 for(m
=0; (m
<DIM
); m
++)
895 gmx_stats_add_point(Qlsq
[m
],0,quad
[m
],0,0);
897 if (bCorr
&& !bTotal
) {
899 muall
[i
][tel3
+XX
] = dipole
[i
][XX
];
900 muall
[i
][tel3
+YY
] = dipole
[i
][YY
];
901 muall
[i
][tel3
+ZZ
] = dipole
[i
][ZZ
];
904 for(m
=0; (m
<DIM
); m
++) {
905 M_av
[m
] += dipole
[i
][m
]; /* M per frame */
906 mu_mol
+= dipole
[i
][m
]*dipole
[i
][m
]; /* calc. mu for distribution */
908 mu_mol
= sqrt(mu_mol
);
910 mu_ave
+= mu_mol
; /* calc. the average mu */
912 /* Update the dipole distribution */
913 ibin
= (int)(ndipbin
*mu_mol
/mu_max
+ 0.5);
918 rvec2sprvec(dipole
[i
],dipsp
[i
]);
920 if (dipsp
[i
][YY
] > -M_PI
&& dipsp
[i
][YY
] < -0.5*M_PI
) {
921 if (dipsp
[i
][ZZ
] < 0.5 * M_PI
) {
926 }else if (dipsp
[i
][YY
] > -0.5*M_PI
&& dipsp
[i
][YY
] < 0.0*M_PI
) {
927 if (dipsp
[i
][ZZ
] < 0.5 * M_PI
) {
932 }else if (dipsp
[i
][YY
] > 0.0 && dipsp
[i
][YY
] < 0.5*M_PI
) {
933 if (dipsp
[i
][ZZ
] < 0.5 * M_PI
) {
938 }else if (dipsp
[i
][YY
] > 0.5*M_PI
&& dipsp
[i
][YY
] < M_PI
) {
939 if (dipsp
[i
][ZZ
] < 0.5 * M_PI
) {
946 fprintf(dip3d
,"set arrow %d from %f, %f, %f to %f, %f, %f lt %d # %d %d\n",
951 x
[ind0
][XX
]+dipole
[i
][XX
]/25,
952 x
[ind0
][YY
]+dipole
[i
][YY
]/25,
953 x
[ind0
][ZZ
]+dipole
[i
][ZZ
]/25,
956 } /* End loop of all molecules in frame */
959 fprintf(dip3d
,"set title \"t = %4.3f\"\n",t
);
960 fprintf(dip3d
,"set xrange [0.0:%4.2f]\n",box
[XX
][XX
]);
961 fprintf(dip3d
,"set yrange [0.0:%4.2f]\n",box
[YY
][YY
]);
962 fprintf(dip3d
,"set zrange [0.0:%4.2f]\n\n",box
[ZZ
][ZZ
]);
963 fprintf(dip3d
,"splot 'dummy.dat' using 1:2:3 w vec\n");
964 fprintf(dip3d
,"pause -1 'Hit return to continue'\n");
968 /* Compute square of total dipole */
969 for(m
=0; (m
<DIM
); m
++)
970 M_av2
[m
] = M_av
[m
]*M_av
[m
];
973 compute_avercos(gnx_tot
,dipole
,&dd
,dipaxis
,bPairs
);
974 rms_cos
= sqrt(sqr(dipaxis
[XX
]-0.5)+
975 sqr(dipaxis
[YY
]-0.5)+
976 sqr(dipaxis
[ZZ
]-0.5));
978 fprintf(caver
,"%10.3e %10.3e %10.3e %10.3e %10.3e %10.3e\n",
979 t
,dd
,rms_cos
,dipaxis
[XX
],dipaxis
[YY
],dipaxis
[ZZ
]);
981 fprintf(caver
,"%10.3e %10.3e %10.3e %10.3e %10.3e\n",
982 t
,rms_cos
,dipaxis
[XX
],dipaxis
[YY
],dipaxis
[ZZ
]);
986 do_gkr(gkrbin
,ncos
,gnx
,molindex
,mols
->index
,x
,dipole
,ePBC
,box
,
992 muall
[0][tel3
+XX
] = M_av
[XX
];
993 muall
[0][tel3
+YY
] = M_av
[YY
];
994 muall
[0][tel3
+ZZ
] = M_av
[ZZ
];
997 /* Write to file the total dipole moment of the box, and its components
1000 if ((skip
== 0) || ((teller
% skip
) == 0))
1001 fprintf(outmtot
,"%10g %12.8e %12.8e %12.8e %12.8e\n",
1002 t
,M_av
[XX
],M_av
[YY
],M_av
[ZZ
],
1003 sqrt(M_av2
[XX
]+M_av2
[YY
]+M_av2
[ZZ
]));
1005 for(m
=0; (m
<DIM
); m
++) {
1008 M4
[m
] += sqr(M_av2
[m
]);
1010 /* Increment loop counter */
1013 /* Calculate for output the running averages */
1014 invtel
= 1.0/teller
;
1015 M2_ave
= (M2
[XX
]+M2
[YY
]+M2
[ZZ
])*invtel
;
1016 M_ave2
= invtel
*(invtel
*(M
[XX
]*M
[XX
] + M
[YY
]*M
[YY
] + M
[ZZ
]*M
[ZZ
]));
1017 M_diff
= M2_ave
- M_ave2
;
1019 /* Compute volume from box in traj, else we use the one from above */
1024 epsilon
= calc_eps(M_diff
,(vol_aver
/teller
),epsilonRF
,temp
);
1026 /* Calculate running average for dipole */
1028 mu_aver
= (mu_ave
/gnx_tot
)*invtel
;
1030 if ((skip
== 0) || ((teller
% skip
) == 0)) {
1031 /* Write to file < |M|^2 >, < |M| >^2. And the difference between
1032 * the two. Here M is sum mu_i. Further write the finite system
1033 * Kirkwood G factor and epsilon.
1035 fprintf(outaver
,"%10g %10.3e %10.3e %10.3e %10.3e\n",
1036 t
,M2_ave
,M_ave2
,M_diff
,M_ave2
/M2_ave
);
1040 gmx_stats_get_average(muframelsq
,&aver
);
1041 fprintf(adip
, "%10g %f \n", t
,aver
);
1044 printf("%f %f\n", norm(dipole[0]), norm(dipole[1]));
1046 if (!bMU
|| (mu_aver
!= -1)) {
1047 /* Finite system Kirkwood G-factor */
1048 Gk
= M_diff
/(gnx_tot
*mu_aver
*mu_aver
);
1049 /* Infinite system Kirkwood G-factor */
1050 if (epsilonRF
== 0.0)
1051 g_k
= ((2*epsilon
+1)*Gk
/(3*epsilon
));
1053 g_k
= ((2*epsilonRF
+epsilon
)*(2*epsilon
+1)*
1054 Gk
/(3*epsilon
*(2*epsilonRF
+1)));
1056 fprintf(outeps
,"%10g %10.3e %10.3e %10.3e\n",t
,epsilon
,Gk
,g_k
);
1060 fprintf(outeps
,"%10g %12.8e\n",t
,epsilon
);
1064 bCont
= read_mu_from_enx(fmu
,iVol
,iMu
,mu_t
,&volume
,&t
,nre
,fr
);
1066 bCont
= read_next_x(oenv
,status
,&t
,natom
,x
,box
);
1083 fprintf(dip3d
,"set xrange [0.0:%4.2f]\n",box
[XX
][XX
]);
1084 fprintf(dip3d
,"set yrange [0.0:%4.2f]\n",box
[YY
][YY
]);
1085 fprintf(dip3d
,"set zrange [0.0:%4.2f]\n\n",box
[ZZ
][ZZ
]);
1086 fprintf(dip3d
,"splot 'dummy.dat' using 1:2:3 w vec\n");
1087 fprintf(dip3d
,"pause -1 'Hit return to continue'\n");
1092 dump_slab_dipoles(slabfn
,idim
,nslices
,slab_dipoles
,box
,teller
,oenv
);
1093 sfree(slab_dipoles
);
1097 printf("Average volume over run is %g\n",vol_aver
);
1099 print_gkrbin(gkrfn
,gkrbin
,gnx
[0],teller
,vol_aver
,oenv
);
1100 print_cmap(cmap
,gkrbin
,nlevels
);
1102 /* Autocorrelation function */
1105 printf("Not enough frames for autocorrelation\n");
1108 dt
=(t1
- t0
)/(teller
-1);
1109 printf("t0 %g, t %g, teller %d\n", t0
,t
,teller
);
1114 do_autocorr(corf
,oenv
,"Autocorrelation Function of Total Dipole",
1115 teller
,1,muall
,dt
,mode
,TRUE
);
1117 do_autocorr(corf
,oenv
,"Dipole Autocorrelation Function",
1118 teller
,gnx_tot
,muall
,dt
,
1119 mode
,strcmp(corrtype
,"molsep"));
1123 real aver
,sigma
,error
,lsq
;
1125 gmx_stats_get_ase(mulsq
,&aver
,&sigma
,&error
);
1126 printf("\nDipole moment (Debye)\n");
1127 printf("---------------------\n");
1128 printf("Average = %8.4f Std. Dev. = %8.4f Error = %8.4f\n",
1133 for(m
=0; (m
<DIM
); m
++)
1134 gmx_stats_get_ase(mulsq
,&(a
[m
]),&(s
[m
]),&(e
[m
]));
1136 printf("\nQuadrupole moment (Debye-Ang)\n");
1137 printf("-----------------------------\n");
1138 printf("Averages = %8.4f %8.4f %8.4f\n",a
[XX
],a
[YY
],a
[ZZ
]);
1139 printf("Std. Dev. = %8.4f %8.4f %8.4f\n",s
[XX
],s
[YY
],s
[ZZ
]);
1140 printf("Error = %8.4f %8.4f %8.4f\n",e
[XX
],e
[YY
],e
[ZZ
]);
1144 printf("The following averages for the complete trajectory have been calculated:\n\n");
1145 printf(" Total < M_x > = %g Debye\n", M
[XX
]/teller
);
1146 printf(" Total < M_y > = %g Debye\n", M
[YY
]/teller
);
1147 printf(" Total < M_z > = %g Debye\n\n", M
[ZZ
]/teller
);
1149 printf(" Total < M_x^2 > = %g Debye^2\n", M2
[XX
]/teller
);
1150 printf(" Total < M_y^2 > = %g Debye^2\n", M2
[YY
]/teller
);
1151 printf(" Total < M_z^2 > = %g Debye^2\n\n", M2
[ZZ
]/teller
);
1153 printf(" Total < |M|^2 > = %g Debye^2\n", M2_ave
);
1154 printf(" Total < |M| >^2 = %g Debye^2\n\n", M_ave2
);
1156 printf(" < |M|^2 > - < |M| >^2 = %g Debye^2\n\n", M_diff
);
1158 if (!bMU
|| (mu_aver
!= -1)) {
1159 printf("Finite system Kirkwood g factor G_k = %g\n", Gk
);
1160 printf("Infinite system Kirkwood g factor g_k = %g\n\n", g_k
);
1162 printf("Epsilon = %g\n", epsilon
);
1165 /* Write to file the dipole moment distibution during the simulation.
1167 outdd
=xvgropen(dipdist
,"Dipole Moment Distribution","mu (Debye)","",oenv
);
1168 for(i
=0; (i
<ndipbin
); i
++)
1169 fprintf(outdd
,"%10g %10f\n",
1170 (i
*mu_max
)/ndipbin
,dipole_bin
[i
]/(double)teller
);
1175 done_gkrbin(&gkrbin
);
1178 void dipole_atom2molindex(int *n
,int *index
,t_block
*mols
)
1186 while(m
< mols
->nr
&& index
[i
] != mols
->index
[m
])
1189 gmx_fatal(FARGS
,"index[%d]=%d does not correspond to the first atom of a molecule",i
+1,index
[i
]+1);
1190 for(j
=mols
->index
[m
]; j
<mols
->index
[m
+1]; j
++) {
1191 if (i
>= *n
|| index
[i
] != j
)
1192 gmx_fatal(FARGS
,"The index group is not a set of whole molecules");
1195 /* Modify the index in place */
1198 printf("There are %d molecules in the selection\n",nmol
);
1202 int gmx_dipoles(int argc
,char *argv
[])
1204 const char *desc
[] = {
1205 "g_dipoles computes the total dipole plus fluctuations of a simulation",
1206 "system. From this you can compute e.g. the dielectric constant for",
1207 "low dielectric media.",
1208 "For molecules with a net charge, the net charge is subtracted at",
1209 "center of mass of the molecule.[PAR]",
1210 "The file Mtot.xvg contains the total dipole moment of a frame, the",
1211 "components as well as the norm of the vector.",
1212 "The file aver.xvg contains < |Mu|^2 > and < |Mu| >^2 during the",
1214 "The file dipdist.xvg contains the distribution of dipole moments during",
1216 "The mu_max is used as the highest value in the distribution graph.[PAR]",
1217 "Furthermore the dipole autocorrelation function will be computed when",
1218 "option -corr is used. The output file name is given with the [TT]-c[tt]",
1220 "The correlation functions can be averaged over all molecules",
1221 "([TT]mol[tt]), plotted per molecule seperately ([TT]molsep[tt])",
1222 "or it can be computed over the total dipole moment of the simulation box",
1223 "([TT]total[tt]).[PAR]",
1224 "Option [TT]-g[tt] produces a plot of the distance dependent Kirkwood",
1225 "G-factor, as well as the average cosine of the angle between the dipoles",
1226 "as a function of the distance. The plot also includes gOO and hOO",
1227 "according to Nymand & Linse, JCP 112 (2000) pp 6386-6395. In the same plot",
1228 "we also include the energy per scale computed by taking the inner product of",
1229 "the dipoles divided by the distance to the third power.[PAR]",
1232 "g_dipoles -corr mol -P1 -o dip_sqr -mu 2.273 -mumax 5.0 -nofft[PAR]",
1233 "This will calculate the autocorrelation function of the molecular",
1234 "dipoles using a first order Legendre polynomial of the angle of the",
1235 "dipole vector and itself a time t later. For this calculation 1001",
1236 "frames will be used. Further the dielectric constant will be calculated",
1237 "using an epsilonRF of infinity (default), temperature of 300 K (default) and",
1238 "an average dipole moment of the molecule of 2.273 (SPC). For the",
1239 "distribution function a maximum of 5.0 will be used."
1241 real mu_max
=5, mu_aver
=-1,rcmax
=0;
1242 real epsilonRF
=0.0, temp
=300;
1243 bool bAverCorr
=FALSE
,bMolCorr
=FALSE
,bPairs
=TRUE
,bPhi
=FALSE
;
1244 const char *corrtype
[]={NULL
, "none", "mol", "molsep", "total", NULL
};
1245 const char *axtitle
="Z";
1246 int nslices
= 10; /* nr of slices defined */
1247 int skip
=0,nFA
=0,nFB
=0,ncos
=1;
1248 int nlevels
=20,ndegrees
=90;
1251 { "-mu", FALSE
, etREAL
, {&mu_aver
},
1252 "dipole of a single molecule (in Debye)" },
1253 { "-mumax", FALSE
, etREAL
, {&mu_max
},
1254 "max dipole in Debye (for histrogram)" },
1255 { "-epsilonRF",FALSE
, etREAL
, {&epsilonRF
},
1256 "epsilon of the reaction field used during the simulation, needed for dieclectric constant calculation. WARNING: 0.0 means infinity (default)" },
1257 { "-skip", FALSE
, etINT
, {&skip
},
1258 "Skip steps in the output (but not in the computations)" },
1259 { "-temp", FALSE
, etREAL
, {&temp
},
1260 "Average temperature of the simulation (needed for dielectric constant calculation)" },
1261 { "-corr", FALSE
, etENUM
, {corrtype
},
1262 "Correlation function to calculate" },
1263 { "-pairs", FALSE
, etBOOL
, {&bPairs
},
1264 "Calculate |cos theta| between all pairs of molecules. May be slow" },
1265 { "-ncos", FALSE
, etINT
, {&ncos
},
1266 "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." },
1267 { "-axis", FALSE
, etSTR
, {&axtitle
},
1268 "Take the normal on the computational box in direction X, Y or Z." },
1269 { "-sl", FALSE
, etINT
, {&nslices
},
1270 "Divide the box in #nr slices." },
1271 { "-gkratom", FALSE
, etINT
, {&nFA
},
1272 "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" },
1273 { "-gkratom2", FALSE
, etINT
, {&nFB
},
1274 "Same as previous option in case ncos = 2, i.e. dipole interaction between two groups of molecules" },
1275 { "-rcmax", FALSE
, etREAL
, {&rcmax
},
1276 "Maximum distance to use in the dipole orientation distribution (with ncos == 2). If zero, a criterium based on the box length will be used." },
1277 { "-phi", FALSE
, etBOOL
, {&bPhi
},
1278 "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." },
1279 { "-nlevels", FALSE
, etINT
, {&nlevels
},
1280 "Number of colors in the cmap output" },
1281 { "-ndegrees", FALSE
, etINT
, {&ndegrees
},
1282 "Number of divisions on the y-axis in the camp output (for 180 degrees)" }
1287 char **grpname
=NULL
;
1288 bool bCorr
,bQuad
,bGkr
,bMU
,bSlab
;
1290 { efEDR
, "-en", NULL
, ffOPTRD
},
1291 { efTRX
, "-f", NULL
, ffREAD
},
1292 { efTPX
, NULL
, NULL
, ffREAD
},
1293 { efNDX
, NULL
, NULL
, ffOPTRD
},
1294 { efXVG
, "-o", "Mtot", ffWRITE
},
1295 { efXVG
, "-eps", "epsilon", ffWRITE
},
1296 { efXVG
, "-a", "aver", ffWRITE
},
1297 { efXVG
, "-d", "dipdist", ffWRITE
},
1298 { efXVG
, "-c", "dipcorr", ffOPTWR
},
1299 { efXVG
, "-g", "gkr", ffOPTWR
},
1300 { efXVG
, "-adip","adip", ffOPTWR
},
1301 { efXVG
, "-dip3d", "dip3d", ffOPTWR
},
1302 { efXVG
, "-cos", "cosaver", ffOPTWR
},
1303 { efXPM
, "-cmap","cmap", ffOPTWR
},
1304 { efXVG
, "-q", "quadrupole", ffOPTWR
},
1305 { efXVG
, "-slab","slab", ffOPTWR
}
1307 #define NFILE asize(fnm)
1315 CopyRight(stderr
,argv
[0]);
1317 ppa
= add_acf_pargs(&npargs
,pa
);
1318 parse_common_args(&argc
,argv
,PCA_CAN_TIME
| PCA_CAN_VIEW
| PCA_BE_NICE
,
1319 NFILE
,fnm
,npargs
,ppa
,asize(desc
),desc
,0,NULL
,&oenv
);
1321 printf("Using %g as mu_max and %g as the dipole moment.\n",
1323 if (epsilonRF
== 0.0)
1324 printf("WARNING: EpsilonRF = 0.0, this really means EpsilonRF = infinity\n");
1326 bMU
= opt2bSet("-en",NFILE
,fnm
);
1327 bQuad
= opt2bSet("-q",NFILE
,fnm
);
1328 bGkr
= opt2bSet("-g",NFILE
,fnm
);
1329 if (opt2parg_bSet("-ncos",asize(pa
),pa
)) {
1330 if ((ncos
!= 1) && (ncos
!= 2))
1331 gmx_fatal(FARGS
,"ncos has to be either 1 or 2");
1334 bSlab
= (opt2bSet("-slab",NFILE
,fnm
) || opt2parg_bSet("-sl",asize(pa
),pa
) ||
1335 opt2parg_bSet("-axis",asize(pa
),pa
));
1339 printf("WARNING: Can not determine quadrupoles from energy file\n");
1343 printf("WARNING: Can not determine Gk(r) from energy file\n");
1348 printf("WARNING: Can not calculate Gk and gk, since you did\n"
1349 " not enter a valid dipole for the molecules\n");
1353 ePBC
= read_tpx_top(ftp2fn(efTPX
,NFILE
,fnm
),NULL
,box
,
1354 &natoms
,NULL
,NULL
,NULL
,top
);
1358 snew(grpindex
,ncos
);
1359 get_index(&top
->atoms
,ftp2fn_null(efNDX
,NFILE
,fnm
),
1360 ncos
,gnx
,grpindex
,grpname
);
1361 for(k
=0; (k
<ncos
); k
++) {
1362 dipole_atom2molindex(&gnx
[k
],grpindex
[k
],&(top
->mols
));
1363 neutralize_mols(gnx
[k
],grpindex
[k
],&(top
->mols
),top
->atoms
.atom
);
1367 do_dip(top
,ePBC
,det(box
),ftp2fn(efTRX
,NFILE
,fnm
),
1368 opt2fn("-o",NFILE
,fnm
),opt2fn("-eps",NFILE
,fnm
),
1369 opt2fn("-a",NFILE
,fnm
),opt2fn("-d",NFILE
,fnm
),
1370 opt2fn_null("-cos",NFILE
,fnm
),
1371 opt2fn_null("-dip3d",NFILE
,fnm
),opt2fn_null("-adip",NFILE
,fnm
),
1373 opt2fn("-c",NFILE
,fnm
),
1374 bGkr
, opt2fn("-g",NFILE
,fnm
),
1375 bPhi
, &nlevels
, ndegrees
,
1377 opt2fn("-cmap",NFILE
,fnm
),rcmax
,
1378 bQuad
, opt2fn("-q",NFILE
,fnm
),
1379 bMU
, opt2fn("-en",NFILE
,fnm
),
1380 gnx
,grpindex
,mu_max
,mu_aver
,epsilonRF
,temp
,nFF
,skip
,
1381 bSlab
,nslices
,axtitle
,opt2fn("-slab",NFILE
,fnm
),oenv
);
1383 do_view(oenv
,opt2fn("-o",NFILE
,fnm
),"-autoscale xy -nxy");
1384 do_view(oenv
,opt2fn("-eps",NFILE
,fnm
),"-autoscale xy -nxy");
1385 do_view(oenv
,opt2fn("-a",NFILE
,fnm
),"-autoscale xy -nxy");
1386 do_view(oenv
,opt2fn("-d",NFILE
,fnm
),"-autoscale xy");
1387 do_view(oenv
,opt2fn("-c",NFILE
,fnm
),"-autoscale xy");