def setUp(self): p = Poscar.from_file(os.path.join(test_dir, 'POSCAR')) self.structure = p.struct self.sg = SymmetryFinder(self.structure, 0.001) parser = CifParser(os.path.join(test_dir, 'Li10GeP2S12.cif')) self.disordered_structure = parser.get_structures()[0] self.disordered_sg = SymmetryFinder(self.disordered_structure, 0.001) s = p.struct editor = StructureEditor(p.struct) site = s[0] editor.delete_site(0) editor.append_site(site.species_and_occu, site.frac_coords) self.sg3 = SymmetryFinder(editor.modified_structure, 0.001)
def test_get_primitive(self): """ F m -3 m Li2O testing of converting to primitive cell """ self.assertIsNone(self.sg.find_primitive()) parser = CifParser(os.path.join(test_dir, 'Li2O.cif')) structure = parser.get_structures(False)[0] s = SymmetryFinder(structure) primitive_structure = s.find_primitive() self.assertEqual(primitive_structure.formula, "Li2 O1") # This isn't what is expected. All the angles should be 60 self.assertAlmostEqual(primitive_structure.lattice.alpha, 120) self.assertAlmostEqual(primitive_structure.lattice.beta, 60) self.assertAlmostEqual(primitive_structure.lattice.gamma, 120) self.assertAlmostEqual(primitive_structure.lattice.volume, structure.lattice.volume / 4.0)
class SpacegroupTest(unittest.TestCase): def setUp(self): p = Poscar.from_file(os.path.join(test_dir, 'POSCAR')) self.structure = p.struct self.sg1 = SymmetryFinder(self.structure, 0.001).get_spacegroup() self.sg2 = Spacegroup.from_spacegroup_number(62) def test_are_symmetrically_equivalent(self): sites1 = [self.structure[i] for i in [0, 1]] sites2 = [self.structure[i] for i in [2, 3]] self.assertTrue(self.sg1.are_symmetrically_equivalent(sites1, sites2, 1e-3)) self.assertTrue(self.sg2.are_symmetrically_equivalent(sites1, sites2, 1e-3)) sites1 = [self.structure[i] for i in [0, 1]] sites2 = [self.structure[i] for i in [0, 2]] self.assertFalse(self.sg1.are_symmetrically_equivalent(sites1, sites2, 1e-3)) self.assertFalse(self.sg2.are_symmetrically_equivalent(sites1, sites2, 1e-3))
class HelperFunctionsTest(unittest.TestCase): def setUp(self): p = Poscar.from_file(os.path.join(test_dir, 'POSCAR')) self.sg = SymmetryFinder(p.struct, 0.1) def test_get_pointgroup(self): (rots, trans) = self.sg.get_symmetry() pg = get_pointgroup(rots) self.assertEqual(pg[0].strip(), "mmm")
parser.add_argument('-f', '--format', dest='format', type=str, nargs=1, choices=['cif', 'poscar'], default='poscar', help='Format of input file. Defaults to POSCAR') parser.add_argument('-t', '--tolerance', dest='tolerance', type=float, nargs=1, help='Tolerance for symmetry determination') args = parser.parse_args() tolerance = float(args.tolerance[0]) if args.tolerance else 0.1 file_format = args.format if args.input_file[0].lower().endswith(".cif"): file_format = "cif" elif args.input_file[0].upper().startswith("POSCAR"): file_format = "poscar" s = None if file_format == 'poscar': p = Poscar.from_file(args.input_file[0]) s = p.struct else: r = CifParser(args.input_file[0]) s = r.get_structures(False)[0] if s: finder = SymmetryFinder(s, tolerance) dataset = finder.get_symmetry_dataset() print "Spacegroup : {}".format(dataset['international']) print "Int number : {}".format(dataset['number']) print "Hall symbol : {}".format(dataset["hall"])
class SymmetryFinderTest(unittest.TestCase): def setUp(self): p = Poscar.from_file(os.path.join(test_dir, 'POSCAR')) self.structure = p.struct self.sg = SymmetryFinder(self.structure, 0.001) parser = CifParser(os.path.join(test_dir, 'Li10GeP2S12.cif')) self.disordered_structure = parser.get_structures()[0] self.disordered_sg = SymmetryFinder(self.disordered_structure, 0.001) s = p.struct editor = StructureEditor(p.struct) site = s[0] editor.delete_site(0) editor.append_site(site.species_and_occu, site.frac_coords) self.sg3 = SymmetryFinder(editor.modified_structure, 0.001) def test_get_space_symbol(self): self.assertEqual(self.sg.get_spacegroup_symbol(), "Pnma") self.assertEqual(self.disordered_sg.get_spacegroup_symbol(), "P4_2/nmc") self.assertEqual(self.sg3.get_spacegroup_symbol(), "Pnma") def test_get_space_number(self): self.assertEqual(self.sg.get_spacegroup_number(), 62) self.assertEqual(self.disordered_sg.get_spacegroup_number(), 137) def test_get_hall(self): self.assertEqual(self.sg.get_hall(), '-P 2ac 2n') self.assertEqual(self.disordered_sg.get_hall(), 'P 4n 2n -1n') def test_get_pointgroup(self): self.assertEqual(self.sg.get_pointgroup(), 'mmm') self.assertEqual(self.disordered_sg.get_pointgroup(), '4/mmm') def test_get_symmetry_dataset(self): ds = self.sg.get_symmetry_dataset() self.assertEqual(ds['international'], 'Pnma') def test_get_crystal_system(self): crystal_system = self.sg.get_crystal_system() self.assertEqual('orthorhombic', crystal_system) self.assertEqual('tetragonal', self.disordered_sg.get_crystal_system()) def test_get_symmetry_operations(self): fracsymmops = self.sg.get_symmetry_operations() symmops = self.sg.get_symmetry_operations(True) self.assertEqual(len(symmops), 8) latt = self.structure.lattice for fop, op in zip(fracsymmops, symmops): for site in self.structure: newfrac = fop.operate(site.frac_coords) newcart = op.operate(site.coords) self.assertTrue(np.allclose(latt.get_fractional_coords(newcart), newfrac)) found = False newsite = PeriodicSite(site.species_and_occu, newcart, latt, coords_are_cartesian=True) for testsite in self.structure: if newsite.is_periodic_image(testsite, 1e-3): found = True break self.assertTrue(found) def test_get_refined_structure(self): for a in self.sg.get_refined_structure().lattice.angles: self.assertEqual(a, 90) refined = self.disordered_sg.get_refined_structure() for a in refined.lattice.angles: self.assertEqual(a, 90) self.assertEqual(refined.lattice.a , refined.lattice.b) def test_get_symmetrized_structure(self): symm_struct = self.sg.get_symmetrized_structure() for a in symm_struct.lattice.angles: self.assertEqual(a, 90) self.assertEqual(len(symm_struct.equivalent_sites), 5) symm_struct = self.disordered_sg.get_symmetrized_structure() self.assertEqual(len(symm_struct.equivalent_sites), 8) def test_get_primitive(self): """ F m -3 m Li2O testing of converting to primitive cell """ self.assertIsNone(self.sg.find_primitive()) parser = CifParser(os.path.join(test_dir, 'Li2O.cif')) structure = parser.get_structures(False)[0] s = SymmetryFinder(structure) primitive_structure = s.find_primitive() self.assertEqual(primitive_structure.formula, "Li2 O1") # This isn't what is expected. All the angles should be 60 self.assertAlmostEqual(primitive_structure.lattice.alpha, 120) self.assertAlmostEqual(primitive_structure.lattice.beta, 60) self.assertAlmostEqual(primitive_structure.lattice.gamma, 120) self.assertAlmostEqual(primitive_structure.lattice.volume, structure.lattice.volume / 4.0)
def setUp(self): p = Poscar.from_file(os.path.join(test_dir, 'POSCAR')) self.sg = SymmetryFinder(p.struct, 0.1)
def setUp(self): p = Poscar.from_file(os.path.join(test_dir, 'POSCAR')) self.structure = p.struct self.sg1 = SymmetryFinder(self.structure, 0.001).get_spacegroup() self.sg2 = Spacegroup.from_spacegroup_number(62)
def __init__( self, structure_a, structure_b, tolerance_cell_misfit=0.1, tolerance_atomic_misfit=1.0, supercells_allowed=True, anonymized=False, fitting_accuracy=FAST_FIT, use_symmetry=False, ): """ Fits two structures. All fitting parameters have been set with defaults that should work in most cases. To use, initialize the structure fitter with parameters. E.g., fitter = StructureFitter(a, b) print fitter.fit_found Args: structure_a : First structure structure_b : Second structure to try to match with first structure tolerance_cell_misfit : Tolerance for cell misfit. Default = 0.1 tolerance_atomic_misfit : Tolerance for atomic misfit. Default = 1.0. supercells_allowed : Whether supercell structures are allowed. Default = True. anonymized : Whether to attempt matching of different species. Setting this to true will allow any two structures with the same framework, but different species to match to each other. Default = False. fitting_accuracy : An integer setting for the fitting accuracy. Corresponds to the max number of candidate rotations considered. Use the static variables, StructureFitter.FAST_FIT StructureFitter.NORMAL_FIT StructureFitter.ACCURATE_FIT to set the tradeoff between accuracy and speed. The default, FAST_FIT, should work reasonably well in most instances. use_symmetry: Whether to use pymatgen.spacegroup to determine the spacegroup first. Eliminates most non-fits. Defaults to True. """ self._tolerance_cell_misfit = tolerance_cell_misfit self._tolerance_atomic_misfit = tolerance_atomic_misfit self._supercells_allowed = supercells_allowed self._anonymized = anonymized self._max_rotations = fitting_accuracy # Sort structures first so that they have the same arrangement of species self._structure_a = structure_a.get_sorted_structure() self._structure_b = structure_b.get_sorted_structure() if use_symmetry: from pymatgen.symmetry.spglib_adaptor import SymmetryFinder finder_a = SymmetryFinder(self._structure_a, symprec=0.1) finder_b = SymmetryFinder(self._structure_b, symprec=0.1) same_sg = finder_a.get_spacegroup_number() == finder_b.get_spacegroup_number() if not use_symmetry or same_sg: self._mapping_op = None if not self._anonymized: self.fit(self._structure_a, self._structure_b) if self.fit_found: self.el_mapping = {el: el for el in self._structure_a.composition.elements} else: comp_a = structure_a.composition comp_b = structure_b.composition if len(comp_a.elements) == len(comp_b.elements): el_a = comp_a.elements # Create permutations of the specie/elements in structure A for p in itertools.permutations(el_a): # Create mapping of the specie/elements in structure B to that of A. # Then create a modified structure with those elements and try to fit it. el_mapping = dict(zip(comp_b.elements, p)) logger.debug("Using specie mapping " + str(el_mapping)) mod = StructureEditor(self._structure_b) mod.replace_species(el_mapping) self.fit(self._structure_a, mod.modified_structure) if self._mapping_op != None: # Store successful element mapping self.el_mapping = {el_a: el_b for el_b, el_a in el_mapping.items()} break else: logger.debug("No. of elements in structures are unequal.") else: self._mapping_op = None logger.debug("Symmetry is different.")