def load_vasprun(filename): from pathlib import Path import xml.etree.ElementTree as ET from chmpy.crystal import UnitCell, Crystal, AsymmetricUnit, SpaceGroup xml = ET.parse(filename) root = xml.getroot() structures = {} atominfo = root.find("atominfo") elements = [] for child in atominfo.findall("array"): if child.get("name") == "atoms": atoms = child.find("set") for atom in atoms.findall("rc"): elements.append(Element[atom.find("c").text]) for structure in root.findall("structure"): name = structure.get("name") crystal = structure.find("crystal") positions = structure.find("varray") direct = None for child in crystal: if child.get("name") == "basis": basis = [] for row in child: basis.append([float(x) for x in row.text.split()]) direct = np.array(basis) pos = [] for row in positions: pos.append([float(x) for x in row.text.split()]) pos = np.array(pos) structures[name] = Crystal( UnitCell(direct), SpaceGroup(1), AsymmetricUnit(elements, pos) ) return structures
def standardize_crystal(crystal, method="spglib", **kwargs): if method != "spglib": raise NotImplementedError("Only spglib is currently supported") lattice = crystal.unit_cell.direct uc_dict = crystal.unit_cell_atoms() positions = uc_dict["frac_pos"] elements = uc_dict["element"] asym_atoms = uc_dict["asym_atom"] asym_labels = uc_dict["label"] cell = lattice, positions, elements reduced_cell = standardize_cell(cell, **kwargs) if reduced_cell is None: LOG.warn("Could not find reduced cell for crystal %s", crystal) return None dataset = get_symmetry_dataset(reduced_cell) asym_idx = np.unique(dataset["equivalent_atoms"]) asym_idx = asym_idx[np.argsort(asym_atoms[asym_idx])] sg = SpaceGroup(dataset["number"], choice=dataset["choice"]) reduced_lattice, positions, elements = reduced_cell unit_cell = UnitCell(reduced_lattice) asym = AsymmetricUnit( [Element[x] for x in elements[asym_idx]], positions[asym_idx], labels=asym_labels[asym_idx], ) return Crystal(unit_cell, sg, asym)
def expand_periodic_images(cell, filename, dest=None, supercell=(1, 1, 1)): frames = parse_traj_file(filename) sg = SpaceGroup(1) xyz_strings = [] for elements, comment, positions in frames: asym = AsymmetricUnit(elements, cell.to_fractional(positions)) c = Crystal(cell, sg, asym).as_P1_supercell(supercell) pos = c.to_cartesian(c.asymmetric_unit.positions) el = c.asymmetric_unit.elements xyz_strings.append(to_xyz_string(el, pos, comment=comment)) if dest is not None: Path(dest).write_text("\n".join(xyz_strings)) else: return "\n".join(xyz_strings)
def load_turbomole_string(tmol_string): from chmpy.util.unit import units "Initialize from an xtb coord string resulting from optimization" data = {} sections = tmol_string.split("$") for section in sections: if not section or section.startswith("end"): continue lines = section.strip().splitlines() label = lines[0].strip() data[label] = [x.strip() for x in lines[1:]] lattice = [] if "lattice bohr" in data else None elements = [] positions = [] for line in data.pop("coord"): x, y, z, el = line.split() positions.append((float(x), float(y), float(z))) elements.append(Element[el]) ANGS = units.angstrom(1.0) pos_cart = np.array(positions) * ANGS result = { "positions": pos_cart, "elements": elements, } if lattice is not None: for line in data.pop("lattice bohr"): lattice.append([float(x) for x in line.split()]) direct = np.array(lattice) * ANGS uc = UnitCell(direct) pos_frac = uc.to_fractional(pos_cart) asym = AsymmetricUnit(elements, pos_frac) result["unit_cell"] = uc result["asymmetric_unit"] = asym result["space_group"] = SpaceGroup(1) result.update(**data) return result
def detect_symmetry(crystal, method="spglib", **kwargs): if method != "spglib": raise NotImplementedError("Only spglib is currently supported") lattice = crystal.unit_cell.direct uc_dict = crystal.unit_cell_atoms() positions = uc_dict["frac_pos"] elements = uc_dict["element"] asym_atoms = uc_dict["asym_atom"] cell = lattice, positions, elements dataset = get_symmetry_dataset(cell, **kwargs) if dataset["number"] == crystal.space_group.international_tables_number: LOG.warn("Could not find additional symmetry for crystal %s", crystal) return None asym_idx = np.unique(dataset["equivalent_atoms"]) asym_idx = asym_idx[np.argsort(asym_atoms[asym_idx])] sg = SpaceGroup(dataset["number"], choice=dataset["choice"]) asym = AsymmetricUnit( [Element[x] for x in dataset["std_types"][asym_idx]], dataset["std_positions"][asym_idx], ) unit_cell = UnitCell(dataset["std_lattice"]) return Crystal(unit_cell, sg, asym)
def test_from_records(self): records = [{"label": "H1", "element": "H", "position": (0, 0, 0)}] asym = AsymmetricUnit.from_records(records) self.assertTrue(len(asym) == 1)
def test_asymmetric_unit_constructor(self): asym = ice_ii_asym() self.assertTrue(len(asym) == 36) asym_generated_labels = AsymmetricUnit(_ICE_II_ELEMENTS, _ICE_II_POSITIONS) self.assertTrue(all(asym_generated_labels.labels == asym.labels))
def ice_ii_asym(): return AsymmetricUnit(_ICE_II_ELEMENTS, _ICE_II_POSITIONS, labels=_ICE_II_LABELS)