def read_data(self, data_file): """Reads a LAMMPS data file. Args: data_file (str): name of LAMMPS data file to read in. """ # Read box, masses and forcefield info from data file. parsable_keywords = {'Masses': self.parse_masses, 'Pair Coeffs': self.parse_pair_coeffs, 'Bond Coeffs': self.parse_bond_coeffs, 'Angle Coeffs': self.parse_angle_coeffs, 'Dihedral Coeffs': self.parse_dihedral_coeffs} with open(data_file, 'r') as data_lines: self.molecule_name = next(data_lines).strip() # Currently only reading a single molecule/moleculeType # per LAMMPS file. self.current_mol = Molecule(self.molecule_name) System._sys.addMolecule(self.current_mol) self.current_mol_type = System._sys._molecules[self.molecule_name] self.current_mol_type.nrexcl = 3 # TODO: automate determination for line in data_lines: if line.strip(): # catch all box dimensions if (('xlo' in line) and ('xhi' in line)): self.parse_box(line.split(), 0) elif (('ylo' in line) and ('yhi' in line)): self.parse_box(line.split(), 1) elif (('zlo' in line) and ('zhi' in line)): self.parse_box(line.split(), 2) # other headers else: keyword = line.strip() if keyword in parsable_keywords: parsable_keywords[keyword](data_lines) # Read atoms, velocities and connectivity information from data file. parsable_keywords = {'Atoms': self.parse_atoms, 'Bonds': self.parse_bonds, 'Angles': self.parse_angles, 'Dihedrals': self.parse_dihedrals} with open(data_file, 'r') as data_lines: for line in data_lines: if line.strip(): keyword = line.strip() if keyword in parsable_keywords: parsable_keywords[keyword](data_lines)
class LammpsParser(object): """A class containing methods to read and write LAMMPS files.""" def __init__(self): """ """ self.box_vector = np.zeros(shape=(3, 3), dtype=float) def read_input(self, input_file): """Reads a LAMMPS input file. Args: input_file (str): Name of LAMMPS input file to read in. """ parsable_keywords = {'units': self.parse_units, 'atom_style': self.parse_atom_style, 'dimension': self.parse_dimension, 'boundary': self.parse_boundary, 'pair_style': self.parse_pair_style, 'kspace_style': self.parse_kspace_style, 'pair_modify': self.parse_pair_modify, 'bond_style': self.parse_bond_style, 'angle_style': self.parse_angle_style, 'dihedral_style': self.parse_dihedral_style, 'improper_style': self.parse_improper_style, 'special_bonds': self.parse_special_bonds} with open(input_file, 'r') as input_lines: for line in input_lines: if line.strip(): keyword = line.split()[0] if keyword in parsable_keywords: parsable_keywords[keyword](line.split()) self.RAD = units.radians self.DEGREE = units.degrees if self.unit_set == 'real': self.DIST = units.angstroms self.VEL = units.angstroms / units.femtosecond self.ENERGY = units.kilocalorie / units.mole self.MASS = units.grams / units.mole self.CHARGE = units.elementary_charge self.MOLE = units.mole else: raise Exception("Unsupported unit set specified in input file: " "{0}".format(unit_set)) def read_data(self, data_file): """Reads a LAMMPS data file. Args: data_file (str): name of LAMMPS data file to read in. """ # Read box, masses and forcefield info from data file. parsable_keywords = {'Masses': self.parse_masses, 'Pair Coeffs': self.parse_pair_coeffs, 'Bond Coeffs': self.parse_bond_coeffs, 'Angle Coeffs': self.parse_angle_coeffs, 'Dihedral Coeffs': self.parse_dihedral_coeffs} with open(data_file, 'r') as data_lines: self.molecule_name = next(data_lines).strip() # Currently only reading a single molecule/moleculeType # per LAMMPS file. self.current_mol = Molecule(self.molecule_name) System._sys.addMolecule(self.current_mol) self.current_mol_type = System._sys._molecules[self.molecule_name] self.current_mol_type.nrexcl = 3 # TODO: automate determination for line in data_lines: if line.strip(): # catch all box dimensions if (('xlo' in line) and ('xhi' in line)): self.parse_box(line.split(), 0) elif (('ylo' in line) and ('yhi' in line)): self.parse_box(line.split(), 1) elif (('zlo' in line) and ('zhi' in line)): self.parse_box(line.split(), 2) # other headers else: keyword = line.strip() if keyword in parsable_keywords: parsable_keywords[keyword](data_lines) # Read atoms, velocities and connectivity information from data file. parsable_keywords = {'Atoms': self.parse_atoms, 'Bonds': self.parse_bonds, 'Angles': self.parse_angles, 'Dihedrals': self.parse_dihedrals} with open(data_file, 'r') as data_lines: for line in data_lines: if line.strip(): keyword = line.strip() if keyword in parsable_keywords: parsable_keywords[keyword](data_lines) def parse_units(self, line): """ """ assert(len(line) == 2), "Invalid units specified in input file." self.unit_set = line[1] def parse_atom_style(self, line): """ Note: Assuming 'full' as default for everything else. """ self.atom_style = line[1] if len(line) > 2: warn("Unsupported atom_style in input file.") def parse_dimension(self, line): """ """ self.dimension = int(line[1]) if self.dimension not in [2, 3]: raise ValueError("Invalid dimension specified in input file" " (must be 2 or 3).") def parse_boundary(self, line): """ """ self.boundaries = [line[1], line[2], line[3]] if len(self.boundaries) != self.dimension: raise ValueError("Boundaries do not match specified dimension " "in input file") def parse_pair_style(self, line): """ """ self.pair_style = [] if line[1] == 'hybrid': warn("Hybrid pair styles not yet implemented.") elif line[1] == 'lj/cut/coul/long': self.pair_style.append(line[1]) System._sys._nbFunc = 1 def parse_kspace_style(self, line): """ Note: Currently ignored. """ if line[1] == 'pppm': pass def parse_pair_modify(self, line): """ """ if line[1] == 'mix': if line[2] == 'geometric': System._sys._combinationRule = 3 elif line[2] == 'arithmetic': System._sys._combinationRule = 2 else: warn("Unsupported pair_modify mix argument in input file!") else: warn("Unsupported pair_modify style in input file!") def parse_bond_style(self, line): """ """ self.bond_style = [] if len(line) == 2: self.bond_style.append(line[1]) elif line[1] == 'hybrid': for style in line[2:]: self.bond_style.append(style) else: raise ValueError("Invalid bond_style in input file!") def parse_angle_style(self, line): """ """ self.angle_style = [] if len(line) == 2: self.angle_style.append(line[1]) elif line[1] == 'hybrid': for style in line[2:]: self.angle_style.append(style) else: raise ValueError("Invalid angle_style in input file!") def parse_dihedral_style(self, line): """ """ self.dihedral_style = [] if len(line) == 2: self.dihedral_style.append(line[1]) # TODO: correctly determine gen-pairs state if self.dihedral_style == 'opls': System._sys._genpairs = 'yes' elif line[1] == 'hybrid': self.dihedral_style = [] for style in line[2:]: self.dihedral_style.append(style) else: raise ValueError("Invalid dihedral_style in input file!") def parse_improper_style(self, line): """ """ self.improper_style = [] if len(line) == 2: self.improper_style.append(line[1]) elif line[1] == 'hybrid': self.improper_style = [] for style in line[2:]: self.improper_style.append(style) else: raise ValueError("Invalid improper_style in input file!") def parse_special_bonds(self, line): """ """ if 'lj/coul' in line: System._sys._ljCorrection = float( line[line.index('lj/coul') + 3]) System._sys._coulombCorrection = float( line[line.index('lj/coul') + 3]) elif 'lj' in line: System._sys._ljCorrection = float( line[line.index('lj') + 3]) elif 'coul' in line: System._sys._coulombCorrection = float( line[line.index('coul') + 3]) else: warn("Unsupported special_bonds in input file.") def parse_box(self, line, dim): """Read box information from data file. Args: line (str): Current line in input file. dim (int): Dimension specified in line. """ fields = [float(field) for field in line[:2]] box_length = fields[1] - fields[0] if box_length > 0: self.box_vector[dim, dim] = box_length else: raise ValueError("Negative box length specified in data file.") System._sys.setBoxVector(self.box_vector * self.DIST) def parse_masses(self, data_lines): """Read masses from data file.""" next(data_lines) # toss out blank line self.mass_dict = dict() for line in data_lines: if not line.strip(): break # found another blank line fields = line.split() self.mass_dict[int(fields[0])] = float(fields[1]) * self.MASS def parse_pair_coeffs(self, data_lines): """Read pair coefficients from data file.""" next(data_lines) # toss out blank line self.nb_types = dict() for line in data_lines: if not line.strip(): break # found another blank line fields = [float(field) for field in line.split()] if len(self.pair_style) == 1: # TODO: lookup of type of pairstyle to determine format if System._sys._nbFunc == 1: self.nb_types[int(fields[0])] = [fields[1] * self.ENERGY, fields[2] * self.DIST] else: warn("Unsupported pair coeff formatting in data file!") else: warn("Unsupported pair coeff formatting in data file!") def parse_bond_coeffs(self, data_lines): """Read bond coefficients from data file.""" next(data_lines) # toss out blank line self.bond_types = dict() for line in data_lines: if not line.strip(): break # found another blank line fields = [float(field) for field in line.split()] if len(self.bond_style) == 1: if 'harmonic' in self.bond_style: self.bond_types[int(fields[0])] = [ 2 * fields[1] * self.ENERGY / (self.DIST*self.DIST), fields[2] * self.DIST] else: warn("Unsupported bond coeff formatting in data file!") else: warn("Unsupported bond coeff formatting in data file!") def parse_angle_coeffs(self, data_lines): """Read angle coefficients from data file.""" next(data_lines) # toss out blank line self.angle_types = dict() for line in data_lines: if not line.strip(): break # found another blank line fields = [float(field) for field in line.split()] if len(self.angle_style) == 1: if 'harmonic' in self.angle_style: self.angle_types[int(fields[0])] = [ 2 * fields[1] * self.ENERGY / (self.RAD*self.RAD), fields[2] * self.DEGREE] else: warn("Unsupported angle coeff formatting in data file!") else: warn("Unsupported angle coeff formatting in data file!") def parse_dihedral_coeffs(self, data_lines): """Read dihedral coefficients from data file.""" next(data_lines) # toss out blank line self.dihedral_types = dict() for line in data_lines: if not line.strip(): break # found another blank line fields = [float(field) for field in line.split()] if len(self.dihedral_style) == 1: if 'opls' in self.dihedral_style: self.dihedral_types[int(fields[0])] = [ fields[1] * self.ENERGY, fields[2] * self.ENERGY, fields[3] * self.ENERGY, fields[4] * self.ENERGY] else: warn("Unsupported dihedral coeff formatting in data file!") else: warn("Unsupported dihedral coeff formatting in data file!") def parse_atoms(self, data_lines): """Read atoms from data file.""" next(data_lines) # toss out blank line for line in data_lines: if not line.strip(): break # found another blank line fields = line.split() if len(fields) in [7, 10]: if len(fields) == 10: # TODO: store image flags? pass new_atom_type = None if System._sys._combinationRule == 1: warn("Combination rule '1' not yet implemented") elif System._sys._combinationRule in [2, 3]: new_atom_type = AtomCR23Type(fields[2], # atomtype fields[2], # bondtype -1, # Z self.mass_dict[int(fields[2])], # mass float(fields[3]) * self.CHARGE, # charge 'A', # ptype self.nb_types[int(fields[2])][1], # sigma self.nb_types[int(fields[2])][0]) # epsilon System._sys._atomtypes.add(new_atom_type) atom = Atom(int(fields[0]), # AtomNum fields[2], # atomName int(fields[1]), # resNum (molNum) fields[1]) # resName (molNum) atom.setAtomType(0, fields[2]) # atomNum for LAMMPS atom.cgnr = 0 # TODO: look into alternatives atom.setCharge(0, float(fields[3]) * self.CHARGE) atom.setMass(0, self.mass_dict[int(fields[2])]) atom.setPosition(float(fields[4]) * self.DIST, float(fields[5]) * self.DIST, float(fields[6]) * self.DIST) for ab_state, atom_type in enumerate(atom._atomtype): # Searching for a matching atom_type temp = AbstractAtomType(atom._atomtype[ab_state]) atom_type = System._sys._atomtypes.get(temp) if atom_type: atom.setSigma(ab_state, atom_type.sigma) atom.setEpsilon(ab_state, atom_type.epsilon) atom.bondtype = atom_type.bondtype else: warn("Corresponding AtomType was not found. " "Insert missing values yourself.") self.current_mol.addAtom(atom) def parse_bonds(self, data_lines): """Read bonds from data file.""" next(data_lines) # toss out blank line for line in data_lines: if not line.strip(): break # found another blank line fields = [int(field) for field in line.split()] new_bond_force = None # TODO: implement bond type creation if len(self.bond_style) == 1: if self.bond_style[0] == 'harmonic': r = self.bond_types[int(fields[1])][1] k = self.bond_types[int(fields[1])][0] new_bond_force = Bond( fields[2], fields[3], r, k) else: warn("Hybrid bond styles not yet implemented") self.current_mol_type.bondForceSet.add(new_bond_force) System._sys._forces.add(new_bond_force) def parse_angles(self, data_lines): """Read angles from data file.""" next(data_lines) # toss out blank line for line in data_lines: if not line.strip(): break # found another blank line fields = [int(field) for field in line.split()] new_angle_force = None if len(self.angle_style) == 1: if self.angle_style[0] == 'harmonic': theta = self.angle_types[int(fields[1])][1] k = self.angle_types[int(fields[1])][0] new_angle_force = Angle( fields[2], fields[3], fields[4], theta, k) else: warn("Hybrid angle styles not yet implemented") self.current_mol_type.angleForceSet.add(new_angle_force) System._sys._forces.add(new_angle_force) def parse_dihedrals(self, data_lines): """Read dihedrals from data file.""" next(data_lines) # toss out blank line for line in data_lines: if not line.strip(): break # found another blank line fields = [int(field) for field in line.split()] new_dihed_force = None if len(self.dihedral_style) == 1: if self.dihedral_style[0] == 'opls': Fs = [self.dihedral_types[int(fields[1])][0], self.dihedral_types[int(fields[1])][1], self.dihedral_types[int(fields[1])][2], self.dihedral_types[int(fields[1])][3]] Cs_temp = ConvertFromOPLSToRBDihedral( Fs[0]._value, Fs[1]._value, Fs[2]._value, Fs[3]._value) Cs = [param * Fs[0].unit for param in Cs_temp] new_dihed_force = RBDihedral( fields[2], fields[3], fields[4], fields[5], Cs[0], Cs[1], Cs[2], Cs[3], Cs[4], Cs[5], Cs[6]) else: warn("Hybrid dihedral styles not yet implemented") self.current_mol_type.dihedralForceSet.add(new_dihed_force) System._sys._forces.add(new_dihed_force) def write(self, data_file, unit_set='real'): """Reads a LAMMPS data file. Args: data_file (str): Name of LAMMPS data file to write to. unit_set (str): LAMMPS unit set for output file. """ self.RAD = units.radians self.DEGREE = units.degrees if unit_set == 'real': self.DIST = units.angstroms self.VEL = units.angstroms / units.femtosecond self.ENERGY = units.kilocalorie / units.mole self.MASS = units.grams / units.mole self.CHARGE = units.elementary_charge self.MOLE = units.mole else: raise Exception("Unsupported unit set specified: {0}".format(unit_set)) # Containers for lines which are ultimately written to output files. mass_list = list() mass_list.append('\n') mass_list.append('Masses\n') mass_list.append('\n') pair_coeff_list = list() pair_coeff_list.append('\n') pair_coeff_list.append('Pair Coeffs\n') pair_coeff_list.append('\n') bond_coeffs = list() bond_coeffs.append('\n') bond_coeffs.append('Bond Coeffs\n') bond_coeffs.append('\n') angle_coeffs = list() angle_coeffs.append('\n') angle_coeffs.append('Angle Coeffs\n') angle_coeffs.append('\n') dihedral_coeffs = list() dihedral_coeffs.append('\n') dihedral_coeffs.append('Dihedral Coeffs\n') dihedral_coeffs.append('\n') improper_coeffs = list() improper_coeffs.append('\n') improper_coeffs.append('Improper Coeffs\n') improper_coeffs.append('\n') atom_list = list() atom_list.append('\n') atom_list.append('Atoms\n') atom_list.append('\n') vel_list = list() vel_list.append('\n') vel_list.append('Velocities\n') vel_list.append('\n') bond_list = list() bond_list.append('\n') bond_list.append('Bonds\n') bond_list.append('\n') angle_list = list() angle_list.append('\n') angle_list.append('Angles\n') angle_list.append('\n') dihedral_list = list() dihedral_list.append('\n') dihedral_list.append('Dihedrals\n') dihedral_list.append('\n') improper_list = list() improper_list.append('\n') improper_list.append('Impropers\n') improper_list.append('\n') # dicts for type information atom_type_dict = dict() # str_type:int_type a_type_i = 1 # counter for atom types bond_style = [] bond_type_dict = dict() # typeObject:int_type b_type_i = 1 # counter for bond types angle_style = [] angle_type_dict = dict() ang_type_i = 1 dihedral_style = [] dihedral_type_dict = dict() dih_type_i = 1 improper_style = [] improper_type_dict = dict() imp_type_i = 1 # read all atom specific and FF information for mol_type in System._sys._molecules.itervalues(): # bond types if mol_type.bondForceSet: for bond in mol_type.bondForceSet.itervalues(): if isinstance(bond, Bond): if 'harmonic' not in bond_style: bond_style.append('harmonic') if len(bond_style) > 1: warn("More than one bond style found!") atom1 = mol_type.moleculeSet[0]._atoms[bond.atom1 - 1] atomtype1 = atom1.bondtype atom2 = mol_type.moleculeSet[0]._atoms[bond.atom2 - 1] atomtype2 = atom2.bondtype temp = BondType( atomtype1, atomtype2, 1, bond.length, bond.k) # NOTE: k includes the factor of 0.5 for harmonic in LAMMPS if temp not in bond_type_dict: bond_type_dict[temp] = b_type_i bond_coeffs.append('{0:d} {1:18.8f} {2:18.8f}\n'.format( b_type_i, 0.5 * bond.k.in_units_of(self.ENERGY / (self.DIST*self.DIST))._value, bond.length.in_units_of(self.DIST)._value)) b_type_i += 1 else: warn("Found unsupported bond type for LAMMPS!") # angle types if mol_type.angleForceSet: for angle in mol_type.angleForceSet.itervalues(): if isinstance(angle, Angle): if 'harmonic' not in angle_style: angle_style.append('harmonic') if len(angle_style) > 1: warn("More than one angle style found!") atom1 = mol_type.moleculeSet[0]._atoms[angle.atom1 - 1] atomtype1 = atom1.bondtype atom2 = mol_type.moleculeSet[0]._atoms[angle.atom2 - 1] atomtype2 = atom2.bondtype atom3 = mol_type.moleculeSet[0]._atoms[angle.atom3 - 1] atomtype3 = atom3.bondtype temp = AngleType(atomtype1, atomtype2, atomtype3, 1, angle.theta, angle.k) # NOTE: k includes the factor of 0.5 for harmonic in LAMMPS if temp not in angle_type_dict: angle_type_dict[temp] = ang_type_i angle_coeffs.append('{0:d} {1:18.8f} {2:18.8f}\n'.format( ang_type_i, 0.5 * angle.k.in_units_of(self.ENERGY / (self.RAD*self.RAD))._value, angle.theta.in_units_of(self.DEGREE)._value)) ang_type_i += 1 else: warn("Found unsupported angle type for LAMMPS!") # dihedral types if mol_type.dihedralForceSet: for dihedral in mol_type.dihedralForceSet.itervalues(): if isinstance(dihedral, ProperDihedral1): continue if isinstance(dihedral, RBDihedral): if 'opls' not in dihedral_style: dihedral_style.append('opls') if len(dihedral_style) > 1: # this may need to be an error # or require some form of conversion if possible warn("More than one dihedral style found!") atom1 = mol_type.moleculeSet[0]._atoms[dihedral.atom1 - 1] atomtype1 = atom1.bondtype atom2 = mol_type.moleculeSet[0]._atoms[dihedral.atom2 - 1] atomtype2 = atom2.bondtype atom3 = mol_type.moleculeSet[0]._atoms[dihedral.atom3 - 1] atomtype3 = atom3.bondtype atom4 = mol_type.moleculeSet[0]._atoms[dihedral.atom4 - 1] atomtype4 = atom4.bondtype temp = RBDihedralType( atomtype1, atomtype2, atomtype3, atomtype4, 3, dihedral.C0, dihedral.C1, dihedral.C2, dihedral.C3, dihedral.C4, dihedral.C5, dihedral.C6) if temp not in dihedral_type_dict: Fs_temp = ConvertFromRBToOPLSDihedral( dihedral.C0._value, dihedral.C1._value, dihedral.C2._value, dihedral.C3._value, dihedral.C4._value, dihedral.C5._value, dihedral.C6._value) Fs = [param * dihedral.C0.unit for param in Fs_temp] dihedral_type_dict[temp] = dih_type_i dihedral_coeffs.append('{0:d} {1:18.8f} {2:18.8f} {3:18.8f} {4:18.8f}\n'.format( dih_type_i, Fs[0].in_units_of(self.ENERGY)._value, Fs[1].in_units_of(self.ENERGY)._value, Fs[2].in_units_of(self.ENERGY)._value, Fs[3].in_units_of(self.ENERGY)._value)) dih_type_i += 1 else: warn("Found unsupported dihedral type for LAMMPS!") # atom specific information x_min = y_min = z_min = np.inf for molecule in mol_type.moleculeSet: for atom in molecule._atoms: # type, mass and pair coeffs if atom._atomtype[0] not in atom_type_dict: atom_type_dict[atom._atomtype[0]] = a_type_i mass_list.append('%d %8.4f\n' % (a_type_i, atom._mass[0].in_units_of(self.MASS)._value)) pair_coeff_list.append('{0:d} {1:8.4f} {2:8.4f}\n'.format( a_type_i, atom._epsilon[0].in_units_of(self.ENERGY)._value, atom._sigma[0].in_units_of(self.DIST)._value)) a_type_i += 1 # box minima x_coord = atom._position[0].in_units_of(self.DIST)._value y_coord = atom._position[1].in_units_of(self.DIST)._value z_coord = atom._position[2].in_units_of(self.DIST)._value if x_coord < x_min: x_min = x_coord if y_coord < y_min: y_min = y_coord if z_coord < z_min: z_min = z_coord # atom atom_list.append('{0:-6d} {1:-6d} {2:-6d} {3:5.8f} {4:8.3f} {5:8.3f} {6:8.3f}\n'.format( atom.atomIndex, atom.residueIndex, atom_type_dict[atom._atomtype[0]], atom._charge[0].in_units_of(self.CHARGE)._value, x_coord, y_coord, z_coord)) # velocity vel_list.append('{0:-6d} {1:8.4f} {2:8.4f} {3:8.4f}\n'.format( atom.atomIndex, atom._velocity[0].in_units_of(self.VEL)._value, atom._velocity[1].in_units_of(self.VEL)._value, atom._velocity[2].in_units_of(self.VEL)._value)) # read all connectivity information for mol_type in System._sys._molecules.itervalues(): # atom index offsets from 1 for each molecule offsets = list() for molecule in mol_type.moleculeSet: offsets.append(molecule._atoms[0].atomIndex - 1) for i, offset in enumerate(offsets): for j, bond in enumerate(mol_type.bondForceSet.itervalues()): atom1 = mol_type.moleculeSet[0]._atoms[bond.atom1 - 1] atomtype1 = atom1.bondtype atom2 = mol_type.moleculeSet[0]._atoms[bond.atom2 - 1] atomtype2 = atom2.bondtype temp = BondType(atomtype1, atomtype2, 1, bond.length, bond.k) bond_list.append('{0:-6d} {1:6d} {2:6d} {3:6d}\n'.format( i + j + 1, bond_type_dict[temp], bond.atom1 + offset, bond.atom2 + offset)) for j, angle in enumerate(mol_type.angleForceSet.itervalues()): atom1 = mol_type.moleculeSet[0]._atoms[angle.atom1 - 1] atomtype1 = atom1.bondtype atom2 = mol_type.moleculeSet[0]._atoms[angle.atom2 - 1] atomtype2 = atom2.bondtype atom3 = mol_type.moleculeSet[0]._atoms[angle.atom3 - 1] atomtype3 = atom3.bondtype temp = AngleType(atomtype1, atomtype2, atomtype3, 1, angle.theta, angle.k) angle_list.append('{0:-6d} {1:6d} {2:6d} {3:6d} {4:6d}\n'.format( i + j + 1, angle_type_dict[temp], angle.atom1 + offset, angle.atom2 + offset, angle.atom3 + offset)) for j, dihedral in enumerate(mol_type.dihedralForceSet.itervalues()): atom1 = mol_type.moleculeSet[0]._atoms[dihedral.atom1 - 1] atomtype1 = atom1.bondtype atom2 = mol_type.moleculeSet[0]._atoms[dihedral.atom2 - 1] atomtype2 = atom2.bondtype atom3 = mol_type.moleculeSet[0]._atoms[dihedral.atom3 - 1] atomtype3 = atom3.bondtype atom4 = mol_type.moleculeSet[0]._atoms[dihedral.atom4 - 1] atomtype4 = atom4.bondtype if isinstance(dihedral, ProperDihedral1): continue temp = RBDihedralType(atomtype1, atomtype2, atomtype3, atomtype4, 3, dihedral.C0, dihedral.C1, dihedral.C2, dihedral.C3, dihedral.C4, dihedral.C5, dihedral.C6) dihedral_list.append('{0:-6d} {1:6d} {2:6d} {3:6d} {4:6d} {5:6d}\n'.format( i + j + 1, dihedral_type_dict[temp], dihedral.atom1 + offset, dihedral.atom2 + offset, dihedral.atom3 + offset, dihedral.atom4 + offset)) # Write the actual data file. with open(data_file, 'w') as f: # front matter f.write(System._sys._name + '\n') f.write('\n') n_atoms = len(atom_list) - 3 n_bonds = len(bond_list) - 3 n_angles = len(angle_list) - 3 n_dihedrals = len(dihedral_list) - 3 n_impropers = len(improper_list) - 3 n_atom_types = len(pair_coeff_list) - 3 n_bond_types = len(bond_coeffs) - 3 n_angle_types = len(angle_coeffs) - 3 n_dihedral_types = len(dihedral_coeffs) - 3 n_improper_types = len(improper_coeffs) - 3 f.write('{0} atoms\n'.format(n_atoms)) f.write('{0} bonds\n'.format(n_bonds)) f.write('{0} angles\n'.format(n_angles)) f.write('{0} dihedrals\n'.format(n_dihedrals)) f.write('{0} impropers\n'.format(n_impropers)) f.write('\n') f.write('{0} atom types\n'.format(n_atom_types)) if n_bond_types > 0: f.write('{0} bond types\n'.format(n_bond_types)) if n_angle_types > 0: f.write('{0} angle types\n'.format(n_angle_types)) if n_dihedral_types > 0: f.write('{0} dihedral types\n'.format(n_dihedral_types)) if n_improper_types > 0: f.write('{0} improper types\n'.format(n_improper_types)) f.write('\n') # shifting of box dimensions f.write('{0:10.6f} {1:10.6f} xlo xhi\n'.format( x_min, x_min + System._sys._boxVector[0][0].in_units_of(self.DIST)._value)) f.write('{0:10.6f} {1:10.6f} ylo yhi\n'.format( y_min, y_min + System._sys._boxVector[1][1].in_units_of(self.DIST)._value)) f.write('{0:10.6f} {1:10.6f} zlo zhi\n'.format( z_min, z_min + System._sys._boxVector[2][2].in_units_of(self.DIST)._value)) # masses for mass in mass_list: f.write(mass) # forcefield coefficients if len(pair_coeff_list) > 3: for pair in pair_coeff_list: f.write(pair) if len(bond_coeffs) > 3: for bond in bond_coeffs: f.write(bond) if len(angle_coeffs) > 3: for angle in angle_coeffs: f.write(angle) if len(dihedral_coeffs) > 3: for dihedral in dihedral_coeffs: f.write(dihedral) if len(improper_coeffs) > 3: for improper in improper_coeffs: f.write(improper) # atoms and velocities for atom in atom_list: f.write(atom) for vel in vel_list: f.write(vel) # topology if len(bond_list) > 3: for bond in bond_list: f.write(bond) if len(angle_list) > 3: for angle in angle_list: f.write(angle) if len(dihedral_list) > 3: for dihedral in dihedral_list: f.write(dihedral) if len(improper_list) > 3: for improper in improper_list: f.write(improper) # Write the corresponding input file. basename = os.path.splitext(data_file)[0] input_filename = '{0}.input'.format(basename) with open(input_filename, 'w') as f: f.write('units {0}\n'.format(unit_set)) f.write('atom_style full\n') # TODO f.write('\n') f.write('dimension 3\n') # TODO f.write('boundary p p p\n') # TODO f.write('\n') # non-bonded f.write('pair_style lj/cut/coul/long 9.0 10.0\n') # TODO: match mdp f.write('pair_modify mix geometric\n') # TODO: match defaults f.write('kspace_style pppm 1.0e-4\n') # TODO: match mdp f.write('\n') # bonded if len(bond_coeffs) > 3: if len(bond_style) == 1: f.write('bond_style {0}\n'.format( " ".join(bond_style))) else: f.write('bond_style hybrid {0}\n'.format( " ".join(bond_style))) if len(angle_coeffs) > 3: if len(angle_style) == 1: f.write('angle_style {0}\n'.format( " ".join(angle_style))) else: f.write('angle_style hybrid {0}\n'.format( " ".join(angle_style))) if len(dihedral_coeffs) > 3: if len(dihedral_style) == 1: f.write('dihedral_style {0}\n'.format( " ".join(dihedral_style))) else: f.write('dihedral_style hybrid {0}\n'.format( " ".join(dihedral_style))) if len(improper_coeffs) > 3: if len(improper_style) == 1: f.write('improper_style {0}\n'.format( " ".join(improper_style))) else: f.write('improper_style hybrid {0}\n'.format( " ".join(improper_style))) f.write('special_bonds lj {0} {1} {2} coul {3} {4} {5}\n'.format( 0.0, 0.0, System._sys._ljCorrection, 0.0, 0.0, System._sys._coulombCorrection)) f.write('\n') # read data f.write('read_data {0}\n'.format(os.path.basename(data_file))) f.write('\n') # output energies energy_terms = " ".join(['ebond', 'eangle', 'edihed', 'eimp', 'epair', 'evdwl', 'ecoul', 'pe']) f.write('thermo_style custom {0}\n'.format(energy_terms)) f.write('\n') f.write('run 0\n')