2"""Heat Flux Correlation function
4Computes the correlation function of the heat flux vector
5that has been stored in a stat file. These can be used to compute
6the thermal conductivity.
11 -h, --help show this help
12 -f, --stat-file=... use specified stat file
13 -o, --output-file=... use specified output (.pcorr) file
14 -e, --einstein use Einstein relation (based on Hess 2002 paper)
16The Einstein relation option will compute: V*<(\int_0^t (S(t')-<S>)dt')^2>/2kT^2,
17which will grow approximately linearly in time. The long-time slope of this
18function will be the viscosity.
21 stat2thcond -f ring5.stat -o ring5.pcorr
25__author__ = "Dan Gezelter (gezelter@nd.edu)"
26__copyright__ = "Copyright (c) 2004-present The University of Notre Dame. All Rights Reserved."
37def readStatFile(statFileName):
54 statFile = open(statFileName, 'r')
61 line = statFile.readline()
63 line = statFile.readline()
67 time.append(float(L[0]))
68 temperature.append(float(L[4]))
70 # OpenMD prints out pressure in units of atm.
72 pressure.append(float(L[5]))
73 volume.append(float(L[6]))
75 # OpenMD prints out heatflux in units of kcal / (mol s Ang^2).
77 Sx.append(float(L[8]))
78 Sy.append(float(L[9]))
79 Sz.append(float(L[10]))
81 line = statFile.readline()
93 print("computing Averages")
105 # converts amu*fs^-2*Ang^-1 -> atm
106 pressureConvert = 1.63882576e8
108 for i in range(len(time)):
109 tempSum = tempSum + temperature[i]
110 pressSum = pressSum + pressure[i]
111 volSum = volSum + volume[i]
112 # in units of amu Ang^2 fs^-1
113 pvTerm = pressure[i]*volume[i] / pressureConvert
114 pvSum = pvSum + pvTerm
115 temp2Sum = temp2Sum + math.pow(temperature[i], 2)
116 press2Sum = press2Sum + math.pow(pressure[i], 2)
117 vol2Sum = vol2Sum + math.pow(volume[i], 2)
118 pv2Sum = pv2Sum + math.pow(pvTerm, 2)
120 tempAve = tempSum / float(len(time))
121 pressAve = pressSum / float(len(time))
122 volAve = volSum / float(len(time))
123 pvAve = pvSum / float(len(time))
125 tempSdev = math.sqrt(temp2Sum / float(len(time)) - math.pow(tempAve, 2))
126 pressSdev = math.sqrt(press2Sum / float(len(time)) - math.pow(pressAve, 2))
127 if (vol2Sum / float(len(time)) < math.pow(volAve, 2)):
130 volSdev = math.sqrt(vol2Sum / float(len(time)) - math.pow(volAve, 2))
131 pvSdev = math.sqrt(pv2Sum / float(len(time)) - math.pow(pvAve, 2))
133 print(" Average pressure = %f +/- %f (atm)" % (pressAve, pressSdev))
134 print(" Average volume = %f +/- %f (Angst^3)" % (volAve, volSdev))
135 print("Average temperature = %f +/- %f (K)" % (tempAve, tempSdev))
136 print(" Average PV product = %f +/- %f (amu Angst^2 fs^-1)" % (pvAve, pvSdev))
138def computeCorrelations(outputFileName):
140 # converts amu*fs^-2*Ang^-1 -> atm
141 pressureConvert = 1.63882576e8
143 # converts Ang^-3 * kcal/mol * Ang / fs to m^-3 * J/mol * m /s (= W / mol m^2)
144 heatfluxConvert = 4.187e38
149 # Boltzmann's constant amu*Ang^2*fs^-2/K
152 # converts Ang^3 / (amu*Ang^2*fs^-2/K * K^2) -> m s^2 / (kg K^2)
153 thcondConvert = 6.0224e-14
155 preV = thcondConvert * volAve / (kB * tempAve * tempAve)
159 print("computing Einstein-style Correlation Function")
161 # Precompute sum variables to aid integration.
162 # The integral from t0 -> t0 + t can be easily obtained
163 # from the precomputed sum variables: sum[t0+t] - sum[t0-1]
171 for i in range(1, len(time)):
172 xSum.append(xSum[i-1] + Sx[i])
173 ySum.append(ySum[i-1] + Sy[i])
174 zSum.append(zSum[i-1] + Sz[i])
176 dt = time[1] - time[0]
182 # i corresponds to the total duration of the integral
183 for i in range(len(time)):
188 # j corresponds to the starting point of the integral
189 for j in range(len(time) - i):
196 xInt = dt*(xSum[j+i] - xSum[j-1])
197 yInt = dt*(ySum[j+i] - ySum[j-1])
198 zInt = dt*(zSum[j+i] - zSum[j-1])
200 xIntSum = xIntSum + xInt*xInt
201 yIntSum = yIntSum + yInt*yInt
202 zIntSum = zIntSum + zInt*zInt
204 eXcorr.append(xIntSum / float(len(time)-i))
205 eYcorr.append(yIntSum / float(len(time)-i))
206 eZcorr.append(zIntSum / float(len(time)-i))
208 outputFile = open(outputFileName, 'w')
209 for i in range(len(time)):
211 outputFile.write("%f\t%13e\n" % (time[i], 0.5 * preV * heatfluxConvert * heatfluxConvert * dtConvert * dtConvert * (eXcorr[i] + eYcorr[i] + eZcorr[i])))
216 global haveStatFileName
217 global haveOutputFileName
219 haveStatFileName = False
220 haveOutputFileName = False
224 opts, args = getopt.getopt(argv, "hgesf:o:", ["help", "einstein", "stat-file=", "output-file="])
225 except getopt.GetoptError:
228 for opt, arg in opts:
229 if opt in ("-h", "--help"):
232 elif opt in ("-e", "--einstein"):
234 elif opt in ("-f", "--stat-file"):
236 haveStatFileName = True
237 elif opt in ("-o", "--output-file"):
239 haveOutputFileName = True
240 if (not haveStatFileName):
242 print("No stat file was specified")
244 if (not haveOutputFileName):
246 print("No output file was specified")
249 readStatFile(statFileName);
251 computeCorrelations(outputFileName);
253if __name__ == "__main__":
254 if len(sys.argv) == 1: