OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
waterRotator
1#!@Python3_EXECUTABLE@
2"""Water Quaternion Sampler
3
4Samples water orientations from a list of known good
5orientations
6
7Usage: waterRotator
8
9Options:
10 -h, --help show this help
11 -m, --meta-data=... use specified meta-data (.omd) file
12 -o, --output-file=... use specified output (.omd) file
13
14
15Example:
16 waterRotator -m basal.omd -o basal.new.omd
17
18"""
19
20__author__ = "Dan Gezelter (gezelter@nd.edu)"
21__copyright__ = "Copyright (c) 2004-present The University of Notre Dame. All Rights Reserved."
22__license__ = "OpenMD"
23
24import sys
25import getopt
26import string
27import math
28import random
29
30_haveMDFileName = 0
31_haveOutputFileName = 0
32
33metaData = []
34frameData = []
35positions = []
36velocities = []
37quaternions = []
38angVels = []
39indices = []
40neighbors = []
41DonatingTo = []
42AcceptingFrom = []
43OldDonor = []
44Hmat = []
45BoxInv = []
46#Hmat = zeros([3,3],Float)
47#BoxInv = zeros([3],Float)
48H1vects = []
49H2vects = []
50DipoleVects = []
51allAcceptors = []
52availableneighbs = []
53surfaceSet = {-1}
54
55
56
57def usage():
58 print(__doc__)
59
60
61def readFile(mdFileName):
62 mdFile = open(mdFileName, 'r')
63 # Find OpenMD version info first
64 line = mdFile.readline()
65 while True:
66 if '<OOPSE version=' in line or '<OpenMD version=' in line:
67 OpenMDversion = line
68 break
69 line = mdFile.readline()
70
71 # Rewind file and find start of MetaData block
72
73 mdFile.seek(0)
74 line = mdFile.readline()
75 print("reading MetaData")
76 while True:
77 if '<MetaData>' in line:
78 while 2:
79 metaData.append(line)
80 line = mdFile.readline()
81 if '</MetaData>' in line:
82 metaData.append(line)
83 break
84 break
85 line = mdFile.readline()
86
87 mdFile.seek(0)
88 print("reading Snapshot")
89 line = mdFile.readline()
90 while True:
91 if '<Snapshot>' in line:
92 line = mdFile.readline()
93 while True:
94 print("reading FrameData")
95 if '<FrameData>' in line:
96 while 2:
97 frameData.append(line)
98 if 'Hmat:' in line:
99 L = line.split()
100 Hxx = float(L[2].strip(','))
101 Hxy = float(L[3].strip(','))
102 Hxz = float(L[4].strip(','))
103 Hyx = float(L[7].strip(','))
104 Hyy = float(L[8].strip(','))
105 Hyz = float(L[9].strip(','))
106 Hzx = float(L[12].strip(','))
107 Hzy = float(L[13].strip(','))
108 Hzz = float(L[14].strip(','))
109 Hmat.append([Hxx, Hxy, Hxz])
110 Hmat.append([Hyx, Hyy, Hyz])
111 Hmat.append([Hzx, Hzy, Hzz])
112 print(Hmat)
113 BoxInv.append(1.0/Hxx)
114 BoxInv.append(1.0/Hyy)
115 BoxInv.append(1.0/Hzz)
116 print(BoxInv)
117 line = mdFile.readline()
118 if '</FrameData>' in line:
119 frameData.append(line)
120 break
121 break
122
123 line = mdFile.readline()
124 while True:
125 if '<StuntDoubles>' in line:
126 line = mdFile.readline()
127 while 2:
128 L = line.split()
129 myIndex = int(L[0])
130 indices.append(myIndex)
131 pvqj = L[1]
132 x = float(L[2])
133 y = float(L[3])
134 z = float(L[4])
135 positions.append([x, y, z])
136 vx = float(L[5])
137 vy = float(L[6])
138 vz = float(L[7])
139 velocities.append([vx, vy, vz])
140 qw = float(L[8])
141 qx = float(L[9])
142 qy = float(L[10])
143 qz = float(L[11])
144 quaternions.append([qw, qx, qy, qz])
145 jx = float(L[12])
146 jy = float(L[13])
147 jz = float(L[14])
148 angVels.append([jx, jy, jz])
149 line = mdFile.readline()
150 if '</StuntDoubles>' in line:
151 break
152 break
153 line = mdFile.readline()
154 if not line: break
155
156 mdFile.close()
157
158def writeFile(outputFileName):
159 outputFile = open(outputFileName, 'w')
160
161 outputFile.write("<OpenMD version=1>\n");
162
163 for metaline in metaData:
164 outputFile.write(metaline)
165
166 outputFile.write(" <Snapshot>\n")
167
168 for frameline in frameData:
169 outputFile.write(frameline)
170
171 outputFile.write(" <StuntDoubles>\n")
172
173 sdFormat = 'pvqj'
174 for i in range(len(indices)):
175
176 outputFile.write("%10d %7s %18.10g %18.10g %18.10g %13e %13e %13e %13e %13e %13e %13e %13e %13e %13e\n" % (indices[i], sdFormat, positions[i][0], positions[i][1], positions[i][2], velocities[i][0], velocities[i][1], velocities[i][2], quaternions[i][0], quaternions[i][1], quaternions[i][2], quaternions[i][3], angVels[i][0], angVels[i][1], angVels[i][2]))
177
178 outputFile.write(" </StuntDoubles>\n")
179 outputFile.write(" </Snapshot>\n")
180 outputFile.write("</OpenMD>\n")
181 outputFile.close()
182
183def roundMe(x):
184 if (x >= 0.0):
185 return math.floor(x + 0.5)
186 else:
187 return math.ceil(x - 0.5)
188
189def wrapVector(myVect):
190 scaled = [0.0, 0.0, 0.0]
191 for i in range(3):
192 scaled[i] = myVect[i] * BoxInv[i]
193 scaled[i] = scaled[i] - roundMe(scaled[i])
194 myVect[i] = scaled[i] * Hmat[i][i]
195 return myVect
196
197def dot(L1, L2):
198 myDot = 0.0
199 for i in range(len(L1)):
200 myDot = myDot + L1[i]*L2[i]
201 return myDot
202
203def normalize(L1):
204 L2 = []
205 myLength = math.sqrt(dot(L1, L1))
206 for i in range(len(L1)):
207 L2.append(L1[i] / myLength)
208 return L2
209
210def cross(L1, L2):
211 # don't call this with anything other than length 3 lists please
212 # or you'll be sorry
213 L3 = [0.0, 0.0, 0.0]
214 L3[0] = L1[1]*L2[2] - L1[2]*L2[1]
215 L3[1] = L1[2]*L2[0] - L1[0]*L2[2]
216 L3[2] = L1[0]*L2[1] - L1[1]*L2[0]
217 return L3
218
219def f(x):
220 return x
221
222def findNeighbors():
223
224 for i in range(len(indices)):
225 neighbors.append(list())
226
227
228 for i in range(len(indices)-1):
229 iPos = positions[i]
230 for j in range(i+1, len(indices)):
231 jPos = positions[j]
232
233 dpos = [jPos[0] - iPos[0], jPos[1]-iPos[1], jPos[2]-iPos[2]]
234 dpos = wrapVector(dpos)
235 dist2 = dot(dpos, dpos)
236
237 if (dist2 < 9.0):
238 neighbors[i].append(j)
239 neighbors[j].append(i)
240
241 if (len(neighbors[i]) == 4):
242 break
243
244 surfaceCount = 0
245 for i in range(len(indices)):
246 if (len(neighbors[i]) < 4):
247 neighbors[i].append(-1)
248 surfaceCount = surfaceCount + 1
249
250 print("surfaceCount = %d" % surfaceCount)
251
252def randomizeProtons():
253
254 # do 10 proton bucket brigades:
255 for i in range(10):
256 origPoint = random.randint(0, len(indices))
257 protonBucketBrigade(origPoint)
258
259 # check to make sure everyone has a happy proton set:
260
261 for j in range(len(indices)):
262 if (len(DonatingTo[j]) != 2):
263 # print "first round to fix molecule %d" % j
264 protonBucketBrigade(j)
265
266 # check to make sure everyone has a happy proton set:
267
268 for j in range(len(indices)):
269 if (len(DonatingTo[j]) != 2):
270 print("second round to fix molecule %d" % j)
271 protonBucketBrigade(j)
272
273 for j in range(len(indices)):
274 if (len(DonatingTo[j]) != 2):
275 print("unfilled proton donor list for molecule %d" % j)
276
277
278
279def protonBucketBrigade(origPoint):
280
281 for i in range(len(indices)):
282 DonatingTo.append(list())
283 AcceptingFrom.append(list())
284 OldDonor.append(list())
285
286 donor = origPoint
287 # pick unreasonable start values (that don't match surface atom
288 # unreasonable values)
289 acceptor = -10
290
291 for i in range(50000):
292 #while (acceptor != origPoint):
293 myNeighbors = set(neighbors[donor])
294
295 # can't pick a proton choice from one of my current protons:
296 badChoices = set(DonatingTo[donor]).union(set(OldDonor[acceptor]))
297 # can't send a proton back to guy who sent one to me (no give-backs):
298 #badChoices.add(set(OldDonor[acceptor]))
299 # can't send a proton to anyone who is already taking 2:
300 for j in myNeighbors.difference(surfaceSet):
301 if (len(AcceptingFrom[j]) == 2):
302 badChoices.add(j)
303
304 nDonors = len(DonatingTo[donor])
305
306 if (nDonors <= 1):
307
308 if (len(myNeighbors.difference(badChoices)) != 0):
309 acceptor = random.choice(list(myNeighbors.difference(badChoices)))
310 else:
311 acceptor = -1
312
313 DonatingTo[donor].append(acceptor)
314
315 if (acceptor != -1):
316 AcceptingFrom[acceptor].append(donor)
317 OldDonor[acceptor].append(donor)
318 elif (nDonors == 2):
319 acceptor = random.choice(DonatingTo[donor])
320 else:
321 print("Whoah! How'd we get here?")
322
323 donor = acceptor
324 if (acceptor == -1):
325 # surface atoms all have a -1 neighbor, but that's OK. A proton
326 # is allowed to point out of the surface, but it does break the
327 # proton chain letter
328 # print "surface atom found, starting over from origPoint"
329 donor = origPoint
330 # break
331
332def computeQuats():
333
334 for i in range(len(indices)):
335 DonatingTo.append(list())
336 AcceptingFrom.append(list())
337 OldDonor.append(list())
338 # print "Computing Quaternions"
339 ux = [0.0, 0.0, 0.0]
340 uy = [0.0, 0.0, 0.0]
341 uz = [0.0, 0.0, 0.0]
342 RotMat = [ux, uy, uz]
343 totalDipole = [0.0, 0.0, 0.0]
344 for i in range(len(indices)):
345 # print "doing quats for molecule %d" % i
346 # print "Dlen = %d " % len(DonatingTo[i])
347 # print DonatingTo[i]
348
349
350 myPos = positions[i]
351
352 acceptor1 = DonatingTo[i][0]
353 acceptor2 = DonatingTo[i][1]
354 if (acceptor1 == -1 and acceptor2 == -1):
355 donor1 = AcceptingFrom[i][0]
356 donor2 = AcceptingFrom[i][1]
357 npos = positions[donor1]
358 apos1 = [npos[0] - myPos[0], npos[1] - myPos[1], npos[2] - myPos[2]]
359 apos1 = wrapVector(apos1)
360 npos = positions[donor2]
361 apos2 = [npos[0] - myPos[0], npos[1] - myPos[1], npos[2] - myPos[2]]
362 apos2 = wrapVector(apos2)
363 tempX = [0.0, 0.0, 0.0]
364 tempY = [0.0, 0.0, 0.0]
365 tempZ = [0.0, 0.0, 0.0]
366 tempZ[0] = 0.5*(apos1[0] + apos2[0])
367 tempZ[1] = 0.5*(apos1[1] + apos2[1])
368 tempZ[2] = 0.5*(apos1[2] + apos2[2])
369 tempX[0] = (apos2[0] - apos1[0])
370 tempX[1] = (apos2[1] - apos1[1])
371 tempX[2] = (apos2[2] - apos1[2])
372 tempZ = normalize(tempZ)
373 tempX = normalize(tempX)
374 tempY = cross(tempX, tempZ)
375 dpos1[0] = tempZ[0] - 0.5*tempY[0]
376 dpos1[1] = tempZ[1] - 0.5*tempY[1]
377 dpos1[2] = tempZ[2] - 0.5*tempY[2]
378 dpos2[0] = tempZ[0] + 0.5*tempY[0]
379 dpos2[1] = tempZ[1] + 0.5*tempY[1]
380 dpos2[2] = tempZ[2] + 0.5*tempY[2]
381
382 else:
383 if (acceptor1 == -1):
384 tempVec = [0.0, 0.0, 0.0]
385 for j in range(3):
386 thisNeighbor = neighbors[i][j]
387 npos = positions[thisNeighbor]
388 npos1 = [npos[0] - myPos[0], npos[1] - myPos[1], npos[2] - myPos[2]]
389 npos1 = wrapVector(npos1)
390 tempVec[0] = tempVec[0] + npos1[0]
391 tempVec[1] = tempVec[1] + npos1[1]
392 tempVec[2] = tempVec[2] + npos1[2]
393 dpos1 = [-tempVec[0]/3.0, -tempVec[1]/3.0, -tempVec[2]/3.0]
394 dpos1 = normalize(dpos1)
395 else:
396 a1pos = positions[acceptor1]
397 dpos1 = [a1pos[0] - myPos[0], a1pos[1] - myPos[1], a1pos[2] - myPos[2]]
398 dpos1 = wrapVector(dpos1)
399 dpos1 = normalize(dpos1)
400
401
402 if (acceptor2 == -1):
403 tempVec = [0.0, 0.0, 0.0]
404 for j in range(3):
405 thisNeighbor = neighbors[i][j]
406 npos = positions[thisNeighbor]
407 npos1 = [npos[0] - myPos[0], npos[1] - myPos[1], npos[2] - myPos[2]]
408 npos1 = wrapVector(npos1)
409 tempVec[0] = tempVec[0] + npos1[0]
410 tempVec[1] = tempVec[1] + npos1[1]
411 tempVec[2] = tempVec[2] + npos1[2]
412 dpos2 = [-tempVec[0]/3.0, -tempVec[1]/3.0, -tempVec[2]/3.0]
413 dpos2 = normalize(dpos2)
414 else:
415 a2pos = positions[acceptor2]
416 dpos2 = [a2pos[0] - myPos[0], a2pos[1] - myPos[1], a2pos[2] - myPos[2]]
417 dpos2 = wrapVector(dpos2)
418 dpos2 = normalize(dpos2)
419
420 for j in range(3):
421 uz[j] = (dpos1[j] + dpos2[j])/2.0
422 uz = normalize(uz)
423 for j in range(3):
424 uy[j] = dpos2[j] - dpos1[j]
425 uy = normalize(uy)
426 ux = cross(uy, uz)
427 ux = normalize(ux)
428
429 q = [0.0, 0.0, 0.0, 0.0]
430
431 # RotMat to Quat code is out of OpenMD's SquareMatrix3.hpp code:
432
433 RotMat[0] = ux
434 RotMat[1] = uy
435 RotMat[2] = uz
436
437 t = RotMat[0][0] + RotMat[1][1] + RotMat[2][2] + 1.0
438
439 if( t > 1e-6 ):
440 s = 0.5 / math.sqrt( t )
441 q[0] = 0.25 / s
442 q[1] = (RotMat[1][2] - RotMat[2][1]) * s
443 q[2] = (RotMat[2][0] - RotMat[0][2]) * s
444 q[3] = (RotMat[0][1] - RotMat[1][0]) * s
445 else:
446 ad1 = RotMat[0][0]
447 ad2 = RotMat[1][1]
448 ad3 = RotMat[2][2]
449
450 if( ad1 >= ad2 and ad1 >= ad3 ):
451 s = 0.5 / math.sqrt( 1.0 + RotMat[0][0] - RotMat[1][1] - RotMat[2][2] )
452 q[0] = (RotMat[1][2] - RotMat[2][1]) * s
453 q[1] = 0.25 / s
454 q[2] = (RotMat[0][1] + RotMat[1][0]) * s
455 q[3] = (RotMat[0][2] + RotMat[2][0]) * s
456 elif ( ad2 >= ad1 and ad2 >= ad3 ):
457 s = 0.5 / math.sqrt( 1.0 + RotMat[1][1] - RotMat[0][0] - RotMat[2][2] )
458 q[0] = (RotMat[2][0] - RotMat[0][2] ) * s
459 q[1] = (RotMat[0][1] + RotMat[1][0]) * s
460 q[2] = 0.25 / s
461 q[3] = (RotMat[1][2] + RotMat[2][1]) * s
462 else:
463 s = 0.5 / math.sqrt( 1.0 + RotMat[2][2] - RotMat[0][0] - RotMat[1][1] )
464 q[0] = (RotMat[0][1] - RotMat[1][0]) * s
465 q[1] = (RotMat[0][2] + RotMat[2][0]) * s
466 q[2] = (RotMat[1][2] + RotMat[2][1]) * s
467 q[3] = 0.25 / s
468
469 quaternions[i] = q
470 totalDipole = [totalDipole[0] + uz[0], totalDipole[1] + uz[1], totalDipole[2] + uz[2]]
471 totalDipole = [-totalDipole[0], -totalDipole[1], -totalDipole[2]]
472 print(totalDipole)
473 Dipole = math.sqrt(dot(totalDipole, totalDipole))
474 print('Total Dipole Moment = %d' % Dipole)
475 if (Dipole > 40 or Dipole < -40):
476 print("Bad Dipole, starting over")
477 for i in range(len(indices)):
478 del OldDonor[:]
479 del AcceptingFrom[:]
480 del DonatingTo[:]
481 # del badChoices[:]
482 randomizeProtons()
483 computeQuats()
484 else:
485 print("All Done!")
486
487
488
489def main(argv):
490 try:
491 opts, args = getopt.getopt(argv, "hm:o:", ["help", "meta-data=", "output-file="])
492 except getopt.GetoptError:
493 usage()
494 sys.exit(2)
495 for opt, arg in opts:
496 if opt in ("-h", "--help"):
497 usage()
498 sys.exit()
499 elif opt in ("-m", "--meta-data"):
500 mdFileName = arg
501 global _haveMDFileName
502 _haveMDFileName = 1
503 elif opt in ("-o", "--output-file"):
504 outputFileName = arg
505 global _haveOutputFileName
506 _haveOutputFileName = 1
507 if (_haveMDFileName != 1):
508 usage()
509 print("No meta-data file was specified")
510 sys.exit()
511 if (_haveOutputFileName != 1):
512 usage()
513 print("No output file was specified")
514 sys.exit()
515 readFile(mdFileName)
516 # analyzeQuats()
517 findNeighbors()
518 randomizeProtons()
519 computeQuats()
520 writeFile(outputFileName)
521
522if __name__ == "__main__":
523 if len(sys.argv) == 1:
524 usage()
525 sys.exit()
526 main(sys.argv[1:])