OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
stat2dielectric
1#!@Python3_EXECUTABLE@
2"""A script that computes the static dielectric constant
3
4Accumulates the static dielectric constant from an OpenMD stat file
5that has been run with the SYSTEM_DIPOLE added to the statFileFormat.
6
7This assumes the fluctuation formula appropriate for conducting
8boundaries:
9
10 <M^2> - <M>^2
11 epsA = 1 + -----------------
12 3 kB <T> <V> eps0
13
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
20
21See M. Neumann, O. Steinhauser, and G. S. Pawley, Mol. Phys. 52, 97 (1984).
22
23Also, optionally applies a correction factor as follows:
24
25 ((Q + 2) (epsA - 1) + 3)
26 eps = ------------------------
27 ((Q - 1) (epsA - 1) + 3)
28
29Where Q depends on the method used to compute the electrostatic interaction.
30See M. Neumann and O. Steinhauser, Chem. Phys. Lett. 95, 417 (1983))
31
32Usage: stat2dielectric
33
34Options:
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
39
40To use this, the OpenMD file for the run should specify:
41
42statFileFormat = "TIME|TOTAL_ENERGY|POTENTIAL_ENERGY|KINETIC_ENERGY|TEMPERATURE|PRESSURE|VOLUME|CONSERVED_QUANTITY|SYSTEM_DIPOLE";
43
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.
48
49Example:
50 stat2dielectric -f stockmayer.stat -o stockmayer.dielectric
51
52"""
53
54__author__ = "Dan Gezelter (gezelter@nd.edu)"
55__copyright__ = "Copyright (c) 2004-present The University of Notre Dame. All Rights Reserved."
56__license__ = "OpenMD"
57
58import sys
59import getopt
60import string
61import math
62
63def usage():
64 print(__doc__)
65
66def readStatFile(statFileName):
67 global time
68 global temperature
69 global volume
70 global boxDipole
71 time = []
72 temperature = []
73 volume = []
74 boxDipole = []
75
76 statFile = open(statFileName, 'r')
77
78 print("reading File")
79 line = statFile.readline()
80 while ("#" in line):
81 line = statFile.readline()
82
83 while True:
84 L = line.split()
85
86 time.append(float(L[0]))
87 temperature.append(float(L[4]))
88 volume.append(float(L[6]))
89 dipX = float(L[-3])
90 dipY = float(L[-2])
91 dipZ = float(L[-1])
92 boxDipole.append([dipX, dipY, dipZ])
93
94 line = statFile.readline()
95 if not line: break
96
97 statFile.close()
98
99def computeAverages(outFileName, Q):
100
101 # permittivity in C^2 N^-1 m^-2
102 eps0 = 8.854187817620E-12
103 # Boltzmann constant in J / K
104 kB = 1.380648E-23
105 # Convert angstroms^3 to m^3
106 a3tom3 = 1.0E-30
107
108 M2 = 0.0
109 M = 0.0
110 Dx = 0.0
111 Dy = 0.0
112 Dz = 0.0
113 Temp = 0.0
114 Vol = 0.0
115
116 print("computing Dielectrics")
117 outFile = open(outFileName, 'w')
118
119 for i in range(len(time)):
120
121 dipX = boxDipole[i][0]
122 dipY = boxDipole[i][1]
123 dipZ = boxDipole[i][2]
124
125 length2 = dipX*dipX + dipY*dipY + dipZ*dipZ
126 M2 += length2
127 M2avg = M2 / float(1+i)
128
129 Dx += dipX
130 Dy += dipY
131 Dz += dipZ
132
133 # the average of each of the three components of the box dipole
134 Mx = Dx / float(1+i)
135 My = Dy / float(1+i)
136 Mz = Dz / float(1+i)
137 Mavg = Mx*Mx + My*My + Mz*Mz
138
139 # the average of the box dipole vector length
140 M += math.sqrt(length2)
141 Mavg2 = M / float(1+i)
142
143 Temp += temperature[i]
144 Tavg = Temp / float(1+i)
145
146 Vol += volume[i] * a3tom3
147 Vavg = Vol / float(1+i)
148
149 x1 = (M2avg - Mavg) / (9.0*eps0*kB*Tavg*Vavg)
150 x2 = (M2avg - Mavg2*Mavg2) / (9.0*eps0*kB*Tavg*Vavg)
151
152 # Clausius-Mossotti
153 d1 = (2.0 * x1 + 1.0) / (1.0 - x1)
154 d2 = (2.0 * x2 + 1.0) / (1.0 - x2)
155
156 # Conducting boundary conditions
157 d3 = 1.0 + 3.0*x1
158 d4 = 1.0 + 3.0*x2
159
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)
162
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)
165
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)
168
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))
170
171 outFile.close()
172
173
174def main(argv):
175 global haveStatFileName
176 global haveOutputFileName
177 global haveQValue
178
179 haveStatFileName = False
180 haveOutputFileName = False
181 haveQValue = False
182
183 try:
184 opts, args = getopt.getopt(argv, "hq:f:o:", ["help", "Q-value=", "stat-file=", "output-file="])
185 except getopt.GetoptError:
186 usage()
187 sys.exit(2)
188 for opt, arg in opts:
189 if opt in ("-h", "--help"):
190 usage()
191 sys.exit()
192 elif opt in ("-q", "--Q-value="):
193 Q = float(arg)
194 haveQValue = True
195 elif opt in ("-f", "--stat-file"):
196 statFileName = arg
197 haveStatFileName = True
198 elif opt in ("-o", "--output-file"):
199 outputFileName = arg
200 haveOutputFileName = True
201 if (not haveStatFileName):
202 usage()
203 print("No stat file was specified")
204 sys.exit()
205 if (not haveOutputFileName):
206 usage()
207 print("No output file was specified")
208 sys.exit()
209
210
211 readStatFile(statFileName)
212 if (not haveQValue):
213 computeAverages(outputFileName, 1.0)
214 else:
215 computeAverages(outputFileName, Q)
216
217
218if __name__ == "__main__":
219 if len(sys.argv) == 1:
220 usage()
221 sys.exit()
222 main(sys.argv[1:])