3__author__ = "Chris Fennell and Dan Gezelter"
4__copyright__ = "Copyright (c) 2004-present The University of Notre Dame. All Rights Reserved."
12from argparse import RawDescriptionHelpFormatter
17# function to calculate the arccosine
19 return math.atan2(math.sqrt(1 - rad * rad), rad)
21# Function to open the output file
22def open_output_file(fileName):
23 f = open(fileName, 'w')
24 if os.path.exists(fileName):
27 sys.exit("Error: can't open file {}\n".format(fileName))
29# Function to find the cutoff
30def find_cutoff(cutoff, boxx, boxy, boxz):
31 bm = min(boxx, boxy, boxz)
33 if boxLength2 <= cutoff:
34 cutoff = int(boxLength2)
36# Functions to print the water model types
43 position(0.0, 0.0, 0.0);
53 position(0.0, 0.0, 0.0);
57def print_ssd_e(outfile):
63 position( 0.0, 0.0, 0.0 );
64 orientation( 0.0, 0.0, 0.0 );
68def print_ssd_rf(outfile):
74 position( 0.0, 0.0, 0.0 );
75 orientation( 0.0, 0.0, 0.0 );
79def print_ssd(outfile):
85 position( 0.0, 0.0, 0.0 );
86 orientation( 0.0, 0.0, 0.0 );
90def print_ssdq(outfile):
96 position( 0.0, 0.0, 0.0 );
97 orientation( 0.0, 0.0, 0.0 );
101def print_ssdqo(outfile):
107 position( 0.0, 0.0, 0.0 );
108 orientation( 0.0, 0.0, 0.0 );
112def print_ssd1(outfile):
118 position( 0.0, 0.0, 0.0 );
119 orientation( 0.0, 0.0, 0.0 );
123def print_tip3p(outfile):
129 position( 0.0, 0.0, -0.06556 );
133 position( 0.0, 0.75695, 0.52032 );
137 position( 0.0, -0.75695, 0.52032 );
144def print_tip4p(outfile):
150 position( 0.0, 0.0, -0.06556 );
154 position( 0.0, 0.75695, 0.52032 );
158 position( 0.0, -0.75695, 0.52032 );
162 position( 0.0, 0.0, 0.08444 );
169def print_tip4p_ice(outfile):
174 type = "O_TIP4P-Ice";
175 position( 0.0, 0.0, -0.06556 );
178 type = "H_TIP4P-Ice";
179 position( 0.0, 0.75695, 0.52032 );
182 type = "H_TIP4P-Ice";
183 position( 0.0, -0.75695, 0.52032 );
186 type = "EP_TIP4P-Ice";
187 position( 0.0, 0.0, 0.09214 );
194def print_tip4p_2005(outfile):
199 type = "O_TIP4P-2005";
200 position( 0.0, 0.0, -0.06556 );
203 type = "H_TIP4P-2005";
204 position( 0.0, 0.75695, 0.52032 );
207 type = "H_TIP4P-2005";
208 position( 0.0, -0.75695, 0.52032 );
211 type = "EP_TIP4P-2005";
212 position( 0.0, 0.0, 0.08904 );
219def print_tip4pew(outfile):
225 position( 0.0, 0.0, -0.06556 );
229 position( 0.0, 0.75695, 0.52032 );
233 position( 0.0, -0.75695, 0.52032 );
236 type = "EP_TIP4P-Ew";
237 position( 0.0, 0.0, 0.05944 );
244def print_tip5p(outfile):
250 position( 0.0, 0.0, -0.06556 );
254 position( 0.0, 0.75695, 0.52032 );
258 position( 0.0, -0.75695, 0.52032 );
262 position( 0.57154, 0.0, -0.46971 );
266 position( -0.57154, 0.0, -0.46971 );
269 members(0, 1, 2, 3, 4);
273def print_tip5pe(outfile):
279 position( 0.0, 0.0, -0.06556 );
283 position( 0.0, 0.75695, 0.52032 );
287 position( 0.0, -0.75695, 0.52032 );
291 position( 0.57154, 0.0, -0.46971 );
295 position( -0.57154, 0.0, -0.46971 );
298 members(0, 1, 2, 3, 4);
302def print_spce(outfile):
308 position( 0.0, 0.0, -0.06461 );
312 position( 0.0, 0.81649, 0.51275 );
316 position( 0.0, -0.81649, 0.51275 );
323def print_spc(outfile):
329 position( 0.0, 0.0, -0.06461 );
333 position( 0.0, 0.81649, 0.51275 );
337 position( 0.0, -0.81649, 0.51275 );
344def print_spc_hw(outfile):
350 position( 0.0, 0.0, -0.06461 );
354 position( 0.0, 0.81649, 0.51275 );
358 position( 0.0, -0.81649, 0.51275 );
365def print_ne6(outfile):
371 position( 0.0, 0.0, 0.0 );
375 position( 0.0, 0.576029, 0.79283665 );
379 position( 0.0, -0.576029, 0.79283665 );
383 position( 0.0, 0.23, 0.0 );
387 position( 0.732813007, -0.50364843, 0.0 );
391 position( -0.732813007, -0.50364843, 0.0 );
394 members(0, 1, 2, 3, 4, 5);
398def print_tip3p_fb(outfile):
404 position( 0.0, 0.0, -0.066424 );
408 position( 0.0, 0.819341, 0.527225 );
412 position( 0.0, -0.819341, 0.527225 );
419def print_tip4p_fb(outfile):
425 position( 0.0, 0.0, -0.0655549 );
429 position( 0.0, 0.75695, 0.520327 );
433 position( 0.0, -0.75695, 0.520327 );
436 type = "EP_TIP4P-FB";
437 position( 0.0, 0.0, 0.0397151 );
444def print_opc(outfile):
450 position( 0.0, 0.0, -0.0603651 );
454 position( 0.0, 0.685582, 0.479134 );
458 position( 0.0, -0.685582, 0.479134 );
462 position( 0.0, 0.0, 0.0990349 );
469def print_opc3(outfile):
475 position( 0.0, 0.0, -0.0632382 );
479 position( 0.0, 0.799262, 0.501939 );
483 position( 0.0, -0.799262, 0.501939 );
490def print_dpd(outfile):
496 position( 0.0, 0.0, 0.0 );
500def print_cg2(outfile):
506 position( 0.0, 0.0, 0.0 );
510# Function to print fake water model
511def print_fake_water(waterName, outfile):
512 outfile.write("\n\nmolecule{{\n name = \"{}\";\n atom[0]{{\n type = \"{}\";\n position(0.0, 0.0, 0.0);\n }}\n}}".format(waterName, waterName))
514# Function to print the water model
515def print_water_model(waterCase, outfile):
516 if waterCase == 0: print_cl(outfile)
517 elif waterCase == 1: print_na(outfile)
518 elif waterCase == 2: print_ssd_e(outfile)
519 elif waterCase == 3: print_ssd_rf(outfile)
520 elif waterCase == 4: print_ssd(outfile)
521 elif waterCase == 5: print_ssd1(outfile)
522 elif waterCase == 6: print_tip3p(outfile)
523 elif waterCase == 7: print_tip4p(outfile)
524 elif waterCase == 8: print_tip4pew(outfile)
525 elif waterCase == 9: print_tip5p(outfile)
526 elif waterCase == 10: print_tip5pe(outfile)
527 elif waterCase == 11: print_spce(outfile)
528 elif waterCase == 12: print_spc(outfile)
529 elif waterCase == 13: print_dpd(outfile)
530 elif waterCase == 14: print_cg2(outfile)
531 elif waterCase == 15: print_ssdq(outfile)
532 elif waterCase == 16: print_ssdqo(outfile)
533 elif waterCase == 17: print_tip4p_ice(outfile)
534 elif waterCase == 18: print_tip4p_2005(outfile)
535 elif waterCase == 19: print_spc_hw(outfile)
536 elif waterCase == 20: print_ne6(outfile)
537 elif waterCase == 21: print_tip3p_fb(outfile)
538 elif waterCase == 22: print_tip4p_fb(outfile)
539 elif waterCase == 23: print_opc(outfile)
540 elif waterCase == 24: print_opc3(outfile)
542# Function to validate the water model
543def validate_water(waterName):
545 'Cl-': 0, 'Na+': 1, 'SSD_E': 2, 'SSD_RF': 3, 'SSD': 4, 'SSD1': 5,
546 'TIP3P': 6, 'TIP4P': 7, 'TIP4P-Ew': 8, 'TIP5P': 9, 'TIP5P-E': 10,
547 'SPCE': 11, 'SPC': 12, 'DPD': 13, 'CG2': 14, 'SSDQ': 15, 'SSDQO': 16,
548 'TIP4P-Ice': 17, 'TIP4P-2005': 18, 'SPC-HW': 19, 'NE6': 20,
549 'TIP3P-FB': 21, 'TIP4P-FB': 22, 'OPC': 23, 'OPC3': 24
551 waterCase = water_models.get(waterName, -1)
555 return (waterCase, invalidWater)
557# Function to print the meta data
558def print_meta_data(outfile, doWaterInc, waterName, waterCase, invalidWater,
559 nMol, cutoff, alpha):
560 outfile.write(" <MetaData>\n")
563 outfile.write('#include "water.inc"')
565 print_water_model(waterCase, outfile)
568 print_fake_water(waterName, outfile)
570 outfile.write("\n\n")
571 outfile.write("component{\n")
572 outfile.write(" type = \"{}\";\n".format(waterName))
573 outfile.write(" nMol = {};\n".format(nMol))
575 outfile.write("ensemble = \"NVT\";\n")
576 outfile.write("forceField = \"Water\";\n")
577 outfile.write("electrostaticSummationMethod = \"shifted_force\";\n")
578 outfile.write("electrostaticScreeningMethod = \"damped\";\n")
579 outfile.write("cutoffRadius = {};\n".format(cutoff))
580 outfile.write("dampingAlpha = {};\n".format(alpha))
582 outfile.write("targetTemp = 300;\n")
583 outfile.write("targetPressure = 1.0;\n")
585 outfile.write("tauThermostat = 1e3;\n")
586 outfile.write("tauBarostat = 1e4;\n")
588 outfile.write("dt = 2.0;\n")
589 outfile.write("runTime = 1e3;\n")
591 outfile.write("tempSet = \"true\";\n")
592 outfile.write("thermalTime = 10;\n")
593 outfile.write("sampleTime = 100;\n")
594 outfile.write("statusTime = 2;\n")
595 outfile.write(" </MetaData>\n")
597# Function to print the frame data
598def print_frame_data(outfile, boxx, boxy, boxz):
599 outfile.write(" <Snapshot>\n")
600 outfile.write(" <FrameData>\n")
601 outfile.write(" Time: 0\n")
602 outfile.write(" Hmat: {{{{ {}, 0, 0 }}, {{ 0, {}, 0 }}, {{ 0, 0, {} }}}}\n".format(boxx, boxy, boxz))
603 outfile.write(" </FrameData>\n")
605# Function to write the output file
606def write_output_file(outfile, nMol, xCorr, yCorr, zCorr, cutoff, alpha,
607 boxx, boxy, boxz, waterName, waterCase, invalidWater,
608 doRandomize, doWaterInc):
609 # Write out the header
610 outfile.write("<OpenMD version=2>\n")
611 find_cutoff(cutoff, boxx, boxy, boxz)
612 print_meta_data(outfile, doWaterInc, waterName, waterCase, invalidWater,
614 print_frame_data(outfile, boxx, boxy, boxz)
615 outfile.write(" <StuntDoubles>\n")
617 # Shift the box center to the origin and write out the coordinates
618 for i in range(nMol):
619 xCorr[i] -= 0.5 * boxx
620 yCorr[i] -= 0.5 * boxy
621 zCorr[i] -= 0.5 * boxz
627 cosTheta = 2.0 * random.random() - 1.0
628 theta = acos(cosTheta)
629 phi = 2.0 * math.pi * random.random()
630 psi = 2.0 * math.pi * random.random()
632 q0 = math.cos(0.5 * theta) * math.cos(0.5 * (phi + psi))
633 q1 = math.sin(0.5 * theta) * math.cos(0.5 * (phi - psi))
634 q2 = math.sin(0.5 * theta) * math.sin(0.5 * (phi - psi))
635 q3 = math.cos(0.5 * theta) * math.sin(0.5 * (phi + psi))
637 outfile.write("{}\tpq\t{} {} {} {} {} {} {}\n".format(i, xCorr[i], yCorr[i], zCorr[i], q0, q1, q2, q3))
639 outfile.write(" </StuntDoubles>\n")
640 outfile.write(" </Snapshot>\n")
641 outfile.write("</OpenMD>\n")
645 parser = argparse.ArgumentParser(
646 description='builds water boxes',
647 formatter_class=argparse.RawDescriptionHelpFormatter,
650Note: you can only use values of x, y, or z that are smaller
651 than the derived box length for a given density and
655 waterBoxer -d 0.997 -x 20 -y 20 -z 20 -w TIP4P-Ice -o tip4pWater.omd
657 parser.add_argument("-d", "--density=", action="store", dest='density',
658 type=float, help="density in g/cm^3",
659 required=False, default=1.0)
660 parser.add_argument("-l", "--lattice=", choices=[0,1],
661 action="store", dest='lattice',
662 type=int, default=0, required=False,
663 help="0 - face centered cubic, 1 - simple cubic")
664 parser.add_argument("-c", "--rcut=", action="store", dest="rcut",
665 type=float, default=3.2, required=False,
666 help="default overlap cutoff in angstroms")
667 parser.add_argument("-o", "--output=", action="store", dest='fileName',
668 help="output file name", required=False,
669 default="freshWater.omd")
670 parser.add_argument("-w", "--water=", action="store", dest="waterName",
671 help="name of the water StuntDouble",
672 required=False, default="SPCE")
673 parser.add_argument("-x", "--boxx=", action="store", required=True,
674 dest='boxx', type=float,
675 help="dimension of the box along the x direction")
676 parser.add_argument("-y", "--boxy=", action="store", required=True,
677 dest='boxy', type=float,
678 help="dimension of the box along the y direction")
679 parser.add_argument("-z", "--boxz=", action="store", required=True,
680 dest='boxz', type=float,
681 help="dimension of the box along the z direction")
682 parser.add_argument("-r", "--randomize",
683 action=argparse.BooleanOptionalAction, default=False,
684 type=bool, dest='doRandomize',
685 help="randomize orientations")
686 parser.add_argument("-m", "--printInclude",
687 action=argparse.BooleanOptionalAction, default=False,
688 type=bool, dest='doWaterInc',
689 help="print out a water.inc file (file with all water models)")
691 if len(sys.argv) == 1:
694 args = parser.parse_args()
696 density = args.density
697 lattice = args.lattice
699 fileName = args.fileName
700 waterName = args.waterName
704 doRandomize = args.doRandomize
705 doWaterInc = args.doWaterInc
708 mass = 2.99151E-23 # mass of H2O in grams
709 cm3ToAng3 = 1E24 # convert cm^3 to angstroms^3
710 densityConvert = mass * cm3ToAng3
717 if fileName == 'water.inc':
718 sys.exit("Error: {} cannot be \"water.inc\"\n Please choose a different name\n".format(fileName))
721 sys.exit("Error: the value for '-d' ({}) is not a valid number\n Please choose a positive real # value\n".format(density))
724 sys.exit("Error: the value for '-c' ({}) is not a valid number\n Please choose a positive real # value\n".format(arg))
725 if lattice != 0 and lattice != 1:
727 sys.exit("Error: the '-l' value ({}) is not a valid number\n Please choose 0 or 1\n".format(arg))
730 sys.exit("Error: the value for '-x' ({}) is not a valid number\n Please choose a positive real # value\n".format(boxx))
733 sys.exit("Error: the value for '-y' ({}) is not a valid number\n Please choose a positive real # value\n".format(boxy))
736 sys.exit("Error: the value for '-z' ({}) is not a valid number\n Please choose a positive real # value\n".format(boxz))
738 outfile = open_output_file(fileName)
740 # Set magic lattice numbers
742 a = (4 * 18.01 / (0.602 * density)) ** (1.0 / 3.0)
743 acut = rcut * math.sqrt(2.0)
746 newDensity = 4.0 * 18.01 / (0.602 * a ** 3)
747 print("using density of {} to match cutoff value ({})\n".format(newDensity, rcut))
749 a = (18.01 / (0.602 * density)) ** (1.0 / 3.0)
753 newDensity = 18.01 / (0.602 * a ** 3)
754 print("using density of {} to match cutoff value ({})\n".format(newDensity, rcut))
757 nx = int(nxFloat + nxFloat / abs(nxFloat * 2))
759 ny = int(nyFloat + nyFloat / abs(nyFloat * 2))
761 nz = int(nzFloat + nzFloat / abs(nzFloat * 2))
763 anew = min(boxx / nx, boxy / ny, boxz / nz)
768 nxFloat = boxx / anew
769 nx = int(nxFloat + nxFloat / abs(nxFloat * 2))
770 nyFloat = boxy / anew
771 ny = int(nyFloat + nyFloat / abs(nyFloat * 2))
772 nzFloat = boxz / anew
773 nz = int(nzFloat + nzFloat / abs(nzFloat * 2))
776 nMol = 4 * nx * ny * nz
780 newDensity = nMol * densityConvert / (boxx * boxy * boxz)
782 if abs(newDensity - density) > tolerance:
783 print("Resetting density to {} to make chosen box sides work out\n".format(newDensity))
785 cellLengthX = boxx / nx
786 cellLengthY = boxy / ny
787 cellLengthZ = boxz / nz
789 cell2X = cellLengthX * 0.5
790 cell2Y = cellLengthY * 0.5
791 cell2Z = cellLengthZ * 0.5
798 xref = [0.0, 0.0, cell2X, cell2X]
799 yref = [0.0, cell2Y, cell2Y, 0.0]
800 zref = [0.0, cell2Z, 0.0, cell2Z]
807 xCorr.append(xref[uc] + cellLengthX * x)
808 yCorr.append(yref[uc] + cellLengthY * y)
809 zCorr.append(zref[uc] + cellLengthZ * z)
820 xCorr.append(xref[uc] + cellLengthX * x)
821 yCorr.append(yref[uc] + cellLengthY * y)
822 zCorr.append(zref[uc] + cellLengthZ * z)
825 (waterCase, invalidWater) = validate_water(waterName)
827 print("Warning: '{}' is not a recognized water model name.\n".format(waterName))
828 print(" Use the '-m' option to generate a 'water.inc' with the\n")
829 print(" recognized water model geometries.\n\n")
830 if waterName == 'DPD':
832 elif waterName == 'CG2':
835 write_output_file(outfile, nMol, xCorr, yCorr, zCorr, cutoff, alpha,
836 boxx, boxy, boxz, waterName, waterCase, invalidWater,
837 doRandomize, doWaterInc)
840 print("The water box \"{}\" was generated.\n".format(fileName))
844 outfile = open("./water.inc", "w")
846 sys.exit("Error: can't open file {}\n".format("water.inc"))
848 outfile.write("#ifndef _WATER_INC_\n#define _WATER_INC_\n")
852 print_ssd_rf(outfile)
857 print_tip4pew(outfile)
859 print_tip5pe(outfile)
866 print_tip4p_ice(outfile)
867 print_tip4p_2005(outfile)
868 print_spc_hw(outfile)
870 print_tip3p_fb(outfile)
871 print_tip4p_fb(outfile)
874 outfile.write("\n\n#endif")
876 print("The file \"water.inc\" was generated for inclusion in \"{}\"\n".format(fileName))
880if __name__ == "__main__":