def test_setters(self, charge, mass): new_type = AtomType(self) new_type.name = "SettingName" new_type.charge = -1.0 * charge new_type.mass = 1 * mass new_type.independent_variables = 'r' new_type.parameters = { 'sigma': 1 * u.nm, 'epsilon': 10 * u.Unit('kcal / mol') } new_type.expression = 'r * sigma * epsilon' assert new_type.name == "SettingName" assert_allclose_units(new_type.charge, -1.0 * charge, rtol=1e-5, atol=1e-8) assert_allclose_units(new_type.mass, 1 * mass, rtol=1e-5, atol=1e-8) assert new_type.independent_variables == {sympy.symbols('r')} assert new_type.parameters == { 'sigma': 1 * u.nm, 'epsilon': 10 * u.Unit('kcal / mol') } assert new_type.expression == sympy.sympify('r * sigma * epsilon')
def _get_ff_information(filename, unit_style, topology): """Parse atom-type information.""" with open(filename, "r") as lammps_file: types = False for i, line in enumerate(lammps_file): if "atom" in line: n_atomtypes = int(line.split()[0]) types = True elif "Masses" in line: break if types == False: return topology mass_lines = open(filename, "r").readlines()[i + 2:i + n_atomtypes + 2] type_list = list() for line in mass_lines: atom_type = AtomType( name=line.split()[0], mass=float(line.split()[1]) * get_units(unit_style)["mass"], ) type_list.append(atom_type) with open(filename, "r") as lammps_file: for i, line in enumerate(lammps_file): if "Pair" in line: break # Need to figure out if we're going have mixing rules printed out # Currently only reading in LJ params pair_lines = open(filename, "r").readlines()[i + 2:i + n_atomtypes + 2] for i, pair in enumerate(pair_lines): if len(pair.split()) == 3: type_list[i].parameters["sigma"] = ( float(pair.split()[2]) * get_units(unit_style)["distance"]) type_list[i].parameters["epsilon"] = ( float(pair.split()[1]) * get_units(unit_style)["energy"]) elif len(pair.split()) == 4: warnings.warn("Currently not reading in mixing rules") return topology, type_list
def _get_ff_information(filename, unit_style, topology): """Function to parse atom-type information """ with open(filename, 'r') as lammps_file: types = False for i, line in enumerate(lammps_file): if 'atom' in line: n_atomtypes = int(line.split()[0]) types = True elif 'Masses' in line: break if types == False: return topology mass_lines = open(filename, 'r').readlines()[i + 2:i + n_atomtypes + 2] type_list = list() for line in mass_lines: atom_type = AtomType(name=line.split()[0], mass=float(line.split()[1]) * get_units(unit_style)['mass']) type_list.append(atom_type) with open(filename, 'r') as lammps_file: for i, line in enumerate(lammps_file): if 'Pair' in line: break # Need to figure out if we're going have mixing rules printed out # Currently only reading in LJ params pair_lines = open(filename, 'r').readlines()[i + 2:i + n_atomtypes + 2] for i, pair in enumerate(pair_lines): if len(pair.split()) == 3: type_list[i].parameters['sigma'] = float( pair.split()[2]) * get_units(unit_style)['distance'] type_list[i].parameters['epsilon'] = float( pair.split()[1]) * get_units(unit_style)['energy'] elif len(pair.split()) == 4: warnings.warn('Currently not reading in mixing rules') return topology, type_list
def test_new_atom_type(self, charge, mass): new_type = AtomType( name="mytype", charge=charge, mass=mass, parameters={ "sigma": 1 * u.nm, "epsilon": 10 * u.Unit("kcal / mol"), }, independent_variables={"r"}, ) assert new_type.name == "mytype" assert_allclose_units(new_type.charge, charge, rtol=1e-5, atol=1e-8) assert_allclose_units( new_type.parameters["sigma"], 1 * u.nm, rtol=1e-5, atol=1e-8 ) assert_allclose_units( new_type.parameters["epsilon"], 10 * u.Unit("kcal / mol"), rtol=1e-5, atol=1e-8, ) assert_allclose_units(new_type.mass, mass, rtol=1e-5, atol=1e-8)
def full_atom_type(self): return AtomType( name="test_atom_type", expression="a*b+c*d+e**2", independent_variables={"a"}, parameters={ "b": 2.0 * u.amu, "c": 3.0 * u.nm / u.kg**2, "d": 5.0 * u.kJ / u.mol, "e": 1.0 * u.C, }, mass=1.0 * u.amu, charge=1.0 * u.elementary_charge, atomclass="test_atom_class", doi="https://dx.doi.org/110.200.300", overrides={"A", "B", "C"}, definition="CX_6", description="A test AtomType object", tags={ "tag1": 10, "tag2": 10 * u.nm }, )
def test_equivalance(self, charge): first_type = AtomType(name='mytype', charge=charge, parameters={'sigma': 1*u.m, 'epsilon': 10*u.m}) same_type = AtomType(name='mytype', charge=charge, parameters={'sigma': 1*u.m, 'epsilon': 10*u.m}) different_name = AtomType(name='difftype', charge=charge, parameters={'sigma': 1*u.m, 'epsilon': 10*u.m}) different_charge = AtomType(name='mytype', charge=4.0 * charge, parameters={'sigma': 1*u.m, 'epsilon': 10*u.m}) different_function = AtomType(name='mytype', charge=charge, parameters={'sigma': 1*u.m, 'epsilon': 10*u.m}, expression='r * sigma * epsilon') different_params = AtomType(name='mytype', charge=charge, parameters={'sigma': 42*u.m, 'epsilon': 100000*u.m}) different_mass = AtomType(name='mytype', charge=charge, mass=5*u.kg/u.mol, parameters={'sigma': 1*u.m, 'epsilon': 10*u.m}) assert first_type == same_type assert first_type != different_name assert first_type != different_charge assert first_type != different_function assert first_type != different_params assert first_type != different_mass
def parse_ff_atomtypes(atomtypes_el, ff_meta): """Given an xml element tree rooted at AtomType, traverse the tree to form a proper topology.core.AtomType.""" atomtypes_dict = {} units_dict = ff_meta["Units"] atom_types_expression = atomtypes_el.attrib.get("expression", None) param_unit_dict = _parse_param_units(atomtypes_el) # Parse all the atomTypes and create a new AtomType for atom_type in atomtypes_el.getiterator("AtomType"): ctor_kwargs = { "name": "AtomType", "mass": 0.0 * u.g / u.mol, "expression": "4*epsilon*((sigma/r)**12 - (sigma/r)**6)", "parameters": None, "charge": 0.0 * u.elementary_charge, "independent_variables": None, "atomclass": "", "doi": "", "overrides": "", "definition": "", "description": "", "topology": None, "element": "", } if atom_types_expression: ctor_kwargs["expression"] = atom_types_expression for kwarg in ctor_kwargs.keys(): ctor_kwargs[kwarg] = atom_type.attrib.get(kwarg, ctor_kwargs[kwarg]) tags = {"tags": {"element": ctor_kwargs.pop("element", "")}} ctor_kwargs.update(tags) if isinstance(ctor_kwargs["mass"], str): ctor_kwargs["mass"] = u.unyt_quantity(float(ctor_kwargs["mass"]), units_dict["mass"]) if isinstance(ctor_kwargs["overrides"], str): ctor_kwargs["overrides"] = set( override.strip() for override in ctor_kwargs["overrides"].split(",")) if isinstance(ctor_kwargs["charge"], str): ctor_kwargs["charge"] = u.unyt_quantity( float(ctor_kwargs["charge"]), units_dict["charge"]) params_dict = _parse_params_values(atom_type, param_unit_dict, "AtomType") if not ctor_kwargs["parameters"] and params_dict: ctor_kwargs["parameters"] = params_dict valued_param_vars = set( sympify(param) for param in params_dict.keys()) ctor_kwargs["independent_variables"] = ( sympify(atom_types_expression).free_symbols - valued_param_vars) _check_valid_string(ctor_kwargs["name"]) this_atom_type = AtomType(**ctor_kwargs) atomtypes_dict[this_atom_type.name] = this_atom_type return atomtypes_dict
def test_incorrect_expression(self, charge): with pytest.raises(ValueError): AtomType(name='mytype', charge=charge, expression=4.2)
def test_incorrect_indep_vars(self): with pytest.raises(ValueError): AtomType(expression='x*y', independent_variables='z')
def read_lammpsdata(filename, atom_style='full'): top = Topology() # The idea is to get the number of types to read in with open(filename, 'r') as lammps_file: for i, line in enumerate(lammps_file): if 'xlo' in line.split(): break typelines = open(filename, 'r').readlines()[2:i] # TODO: Rewrite the logic to read in all type information for line in typelines: if 'atoms' in line: n_atoms = int(line.split()[0]) elif 'bonds' in line: n_bonds = int(line.split()[0]) elif 'angles' in line: n_angles = int(line.split()[0]) elif 'dihedrals' in line: n_dihedrals = int(line.split()[0]) elif 'impropers' in line: n_impropers = int(line.split()[0]) elif 'atom' in line: n_atomtypes = int(line.split()[0]) elif 'bond' in line: n_bondtypes = int(line.split()[0]) elif 'angle' in line: n_angletypes = int(line.split()[0]) elif 'dihedral' in line: n_dihedraltypes = int(line.split()[0]) with open(filename, 'r') as lammps_file: top.name = str(lammps_file.readline().strip()) lammps_file.readline() for j in range( i - 2): # looping through to skip through all of the type lines lammps_file.readline() x_line = lammps_file.readline().split() y_line = lammps_file.readline().split() z_line = lammps_file.readline().split() x = float(x_line[1]) - float(x_line[0]) y = float(y_line[1]) - float(y_line[0]) z = float(z_line[1]) - float(z_line[0]) # Box Information lengths = u.unyt_array([x, y, z], u.angstrom) top.box = Box(lengths) coords = u.angstrom * np.zeros(shape=(n_atoms, 3)) unique_types = _get_masses(filename, n_atomtypes) charge_dict, coords_dict, type_dict = _get_atoms(filename, n_atoms, coords) sigma_dict, epsilon_dict = _get_pairs(filename, n_atomtypes) for k, v in type_dict.items(): atomtype = AtomType(name=k, mass=unique_types[k], charge=charge_dict[k], parameters={ 'sigma': sigma_dict[k], 'epsilon': epsilon_dict[k] }) for i in range(v): site = Site( name="atom{}".format(i), # probably change position=coords_dict[k][i], atom_type=atomtype) top.add_site(site, update_types=False) print('{}:{}'.format(k, i)) top.update_topology() return top