2"""A script that computes the static dielectric constant
4Accumulates the static dielectric constant from an OpenMD stat file
5that has been run with the SYSTEM_DIPOLE added to the statFileFormat.
7This assumes the fluctuation formula appropriate for conducting
11 epsA = 1 + -----------------
14 epsA: dielectric constant
15 M: total dipole moment of the box
16 <V>: average volume of the box
17 <T>: average temperature
18 eps0: vacuum permittivity
19 kB: Boltzmann constant
21See M. Neumann, O. Steinhauser, and G. S. Pawley, Mol. Phys. 52, 97 (1984).
23Also, optionally applies a correction factor as follows:
25 ((Q + 2) (epsA - 1) + 3)
26 eps = ------------------------
27 ((Q - 1) (epsA - 1) + 3)
29Where Q depends on the method used to compute the electrostatic interaction.
30See M. Neumann and O. Steinhauser, Chem. Phys. Lett. 95, 417 (1983))
35 -h, --help show this help
36 -f, --stat-file=... use specified stat file
37 -o, --output-file=... use specified output (.dielectric) file
38 -q, --Q-value=... use the specified Q value to correct the dielectric
40To use this, the OpenMD file for the run should specify:
42statFileFormat = "TIME|TOTAL_ENERGY|POTENTIAL_ENERGY|KINETIC_ENERGY|TEMPERATURE|PRESSURE|VOLUME|CONSERVED_QUANTITY|SYSTEM_DIPOLE";
44This line will get OpenMD to compute the total system dipole and place
45it in the final three columns of the stat file. The stat2dielectric
46script looks for the temperature in column 5, the volume in column 7,
47and the dipole vector in the last 3 columns of the stat file.
50 stat2dielectric -f stockmayer.stat -o stockmayer.dielectric
54__author__ = "Dan Gezelter (gezelter@nd.edu)"
55__copyright__ = "Copyright (c) 2004-present The University of Notre Dame. All Rights Reserved."
66def readStatFile(statFileName):
76 statFile = open(statFileName, 'r')
79 line = statFile.readline()
81 line = statFile.readline()
86 time.append(float(L[0]))
87 temperature.append(float(L[4]))
88 volume.append(float(L[6]))
92 boxDipole.append([dipX, dipY, dipZ])
94 line = statFile.readline()
99def computeAverages(outFileName, Q):
101 # permittivity in C^2 N^-1 m^-2
102 eps0 = 8.854187817620E-12
103 # Boltzmann constant in J / K
105 # Convert angstroms^3 to m^3
116 print("computing Dielectrics")
117 outFile = open(outFileName, 'w')
119 for i in range(len(time)):
121 dipX = boxDipole[i][0]
122 dipY = boxDipole[i][1]
123 dipZ = boxDipole[i][2]
125 length2 = dipX*dipX + dipY*dipY + dipZ*dipZ
127 M2avg = M2 / float(1+i)
133 # the average of each of the three components of the box dipole
137 Mavg = Mx*Mx + My*My + Mz*Mz
139 # the average of the box dipole vector length
140 M += math.sqrt(length2)
141 Mavg2 = M / float(1+i)
143 Temp += temperature[i]
144 Tavg = Temp / float(1+i)
146 Vol += volume[i] * a3tom3
147 Vavg = Vol / float(1+i)
149 x1 = (M2avg - Mavg) / (9.0*eps0*kB*Tavg*Vavg)
150 x2 = (M2avg - Mavg2*Mavg2) / (9.0*eps0*kB*Tavg*Vavg)
153 d1 = (2.0 * x1 + 1.0) / (1.0 - x1)
154 d2 = (2.0 * x2 + 1.0) / (1.0 - x2)
156 # Conducting boundary conditions
160 #d1 = 1.0 + (M2avg - Mavg) / (3.0*eps0*kB*Tavg*Vavg)
161 #d2 = 1.0 + (M2avg - Mavg2*Mavg2) / (3.0*eps0*kB*Tavg*Vavg)
163 corrected1 = ((Q+2.0)*(d3 - 1.0) + 3.0)/((Q-1.0) * (d3 - 1.0) + 3.0)
164 corrected2 = ((Q+2.0)*(d4 - 1.0) + 3.0)/((Q-1.0) * (d4 - 1.0) + 3.0)
166 #corrected1 = (1.0 + 2.0*x1 + Q*x1)/(1.0 - x1 - Q*x1)
167 #corrected2 = (1.0 + 2.0*x2 + Q*x2)/(1.0 - x2 - Q*x2)
169 outFile.write("%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\n" % (time[i], x1, x2, d1, d2, d3, d4, corrected1, corrected2))
175 global haveStatFileName
176 global haveOutputFileName
179 haveStatFileName = False
180 haveOutputFileName = False
184 opts, args = getopt.getopt(argv, "hq:f:o:", ["help", "Q-value=", "stat-file=", "output-file="])
185 except getopt.GetoptError:
188 for opt, arg in opts:
189 if opt in ("-h", "--help"):
192 elif opt in ("-q", "--Q-value="):
195 elif opt in ("-f", "--stat-file"):
197 haveStatFileName = True
198 elif opt in ("-o", "--output-file"):
200 haveOutputFileName = True
201 if (not haveStatFileName):
203 print("No stat file was specified")
205 if (not haveOutputFileName):
207 print("No output file was specified")
211 readStatFile(statFileName)
213 computeAverages(outputFileName, 1.0)
215 computeAverages(outputFileName, Q)
218if __name__ == "__main__":
219 if len(sys.argv) == 1: