Пример #1
0
    def test_ignore_species(self):
        s1 = Structure.from_file(os.path.join(test_dir, "LiFePO4.cif"))
        s2 = Structure.from_file(os.path.join(test_dir, "POSCAR"))
        m = StructureMatcher(ignored_species=["Li"],
                             primitive_cell=False,
                             attempt_supercell=True)
        self.assertTrue(m.fit(s1, s2))
        self.assertTrue(m.fit_anonymous(s1, s2))
        groups = m.group_structures([s1, s2])
        self.assertEqual(len(groups), 1)
        s2.make_supercell((2, 1, 1))
        ss1 = m.get_s2_like_s1(s2, s1, include_ignored_species=True)
        self.assertAlmostEqual(ss1.lattice.a, 20.820740000000001)
        self.assertEqual(ss1.composition.reduced_formula, "LiFePO4")

        self.assertEqual(
            {
                k.symbol: v.symbol
                for k, v in m.get_best_electronegativity_anonymous_mapping(
                    s1, s2).items()
            }, {
                "Fe": "Fe",
                "P": "P",
                "O": "O"
            })
Пример #2
0
    def apply_transformation(self, structure):
        """
        Returns a copy of structure with lattice parameters
        and sites scaled to the same degree as the relaxed_structure.

        Arg:
            structure (Structure): A structurally similar structure in
                regards to crystal and site positions.
        """

        if self.species_map is None:
            match = StructureMatcher()
            s_map = match.get_best_electronegativity_anonymous_mapping(self.unrelaxed_structure, structure)
        else:
            s_map = self.species_map

        params = list(structure.lattice.abc)
        params.extend(structure.lattice.angles)
        new_lattice = Lattice.from_parameters(*(p * self.params_percent_change[i] for i, p in enumerate(params)))
        species, frac_coords = [], []
        for site in self.relaxed_structure:
            species.append(s_map[site.specie])
            frac_coords.append(site.frac_coords)

        return Structure(new_lattice, species, frac_coords)
Пример #3
0
    def apply_transformation(self, structure):
        """
        Returns a copy of structure with lattice parameters
        and sites scaled to the same degree as the relaxed_structure.

        Arg:
            structure (Structure): A structurally similar structure in
                regards to crystal and site positions.
        """

        if self.species_map == None:
            match = StructureMatcher()
            s_map = \
                match.get_best_electronegativity_anonymous_mapping(self.unrelaxed_structure,
                                                                   structure)
        else:
            s_map = self.species_map

        params = list(structure.lattice.abc)
        params.extend(structure.lattice.angles)
        new_lattice = Lattice.from_parameters(*[p*self.params_percent_change[i] \
                                                for i, p in enumerate(params)])
        species, frac_coords = [], []
        for site in self.relaxed_structure:
            species.append(s_map[site.specie])
            frac_coords.append(site.frac_coords)

        return Structure(new_lattice, species, frac_coords)
Пример #4
0
    def test_electronegativity(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5)

        s1 = Structure.from_file(os.path.join(test_dir, "Na2Fe2PAsO4S4.json"))
        s2 = Structure.from_file(os.path.join(test_dir, "Na2Fe2PNO4Se4.json"))
        self.assertEqual(sm.get_best_electronegativity_anonymous_mapping(s1, s2),
                    {Element('S'): Element('Se'),
                     Element('As'): Element('N'),
                     Element('Fe'): Element('Fe'),
                     Element('Na'): Element('Na'),
                     Element('P'): Element('P'),
                     Element('O'): Element('O'),})
        self.assertEqual(len(sm.get_all_anonymous_mappings(s1, s2)), 2)
Пример #5
0
    def test_electronegativity(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5)

        s1 = Structure.from_file(os.path.join(test_dir, "Na2Fe2PAsO4S4.json"))
        s2 = Structure.from_file(os.path.join(test_dir, "Na2Fe2PNO4Se4.json"))
        self.assertEqual(sm.get_best_electronegativity_anonymous_mapping(s1, s2),
                    {Element('S'): Element('Se'),
                     Element('As'): Element('N'),
                     Element('Fe'): Element('Fe'),
                     Element('Na'): Element('Na'),
                     Element('P'): Element('P'),
                     Element('O'): Element('O'),})
        self.assertEqual(len(sm.get_all_anonymous_mappings(s1, s2)), 2)
Пример #6
0
    def predict(self, structure, ref_structure, test_isostructural=True):
        """
        Given a structure, returns back the predicted volume.

        Args:
            structure (Structure): structure w/unknown volume
            ref_structure (Structure): A reference structure with a similar
                structure but different species.
            test_isostructural (bool): Whether to test that the two
                structures are isostructural. This algo works best for
                isostructural compounds. Defaults to True.

        Returns:
            a float value of the predicted volume
        """
        if not is_ox(structure):
            a = BVAnalyzer()
            structure = a.get_oxi_state_decorated_structure(structure)
        if not is_ox(ref_structure):
            a = BVAnalyzer()
            ref_structure = a.get_oxi_state_decorated_structure(ref_structure)

        if test_isostructural:
            m = StructureMatcher()
            mapping = m.get_best_electronegativity_anonymous_mapping(
                structure, ref_structure)
            if mapping is None:
                raise ValueError("Input structures do not match!")

        comp = structure.composition
        ref_comp = ref_structure.composition

        numerator = 0
        denominator = 0

        # Here, the 1/3 factor on the composition accounts for atomic
        # packing. We want the number per unit length.

        # TODO: AJ doesn't understand the (1/3). It would make sense to him
        # if you were doing atomic volume and not atomic radius
        for k, v in comp.items():
            numerator += k.ionic_radius * v**(1 / 3)
        for k, v in ref_comp.items():
            denominator += k.ionic_radius * v**(1 / 3)

        # The scaling factor is based on lengths. We apply a power of 3.
        return ref_structure.volume * (numerator / denominator)**3
Пример #7
0
    def test_electronegativity(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5)

        s1 = Structure.from_file(os.path.join(test_dir, "Na2Fe2PAsO4S4.json"))
        s2 = Structure.from_file(os.path.join(test_dir, "Na2Fe2PNO4Se4.json"))
        self.assertEqual(
            sm.get_best_electronegativity_anonymous_mapping(s1, s2),
            {
                Element("S"): Element("Se"),
                Element("As"): Element("N"),
                Element("Fe"): Element("Fe"),
                Element("Na"): Element("Na"),
                Element("P"): Element("P"),
                Element("O"): Element("O"),
            },
        )
        self.assertEqual(len(sm.get_all_anonymous_mappings(s1, s2)), 2)
Пример #8
0
    def test_ignore_species(self):
        s1 = Structure.from_file(os.path.join(test_dir, "LiFePO4.cif"))
        s2 = Structure.from_file(os.path.join(test_dir, "POSCAR"))
        m = StructureMatcher(ignored_species=["Li"], primitive_cell=False, attempt_supercell=True)
        self.assertTrue(m.fit(s1, s2))
        self.assertTrue(m.fit_anonymous(s1, s2))
        groups = m.group_structures([s1, s2])
        self.assertEqual(len(groups), 1)
        s2.make_supercell((2, 1, 1))
        ss1 = m.get_s2_like_s1(s2, s1, include_ignored_species=True)
        self.assertAlmostEqual(ss1.lattice.a, 20.820740000000001)
        self.assertEqual(ss1.composition.reduced_formula, "LiFePO4")

        self.assertEqual(
            {k.symbol: v.symbol for k, v in m.get_best_electronegativity_anonymous_mapping(s1, s2).items()},
            {"Fe": "Fe", "P": "P", "O": "O"},
        )
Пример #9
0
    def predict(self, structure, ref_structure, test_isostructural=True):
        """
        Given a structure, returns back the predicted volume.

        Args:
            structure (Structure): structure w/unknown volume
            ref_structure (Structure): A reference structure with a similar
                structure but different species.
            test_isostructural (bool): Whether to test that the two
                structures are isostructural. This algo works best for
                isostructural compounds. Defaults to True.

        Returns:
            a float value of the predicted volume
        """
        if not is_ox(structure):
            a = BVAnalyzer()
            structure = a.get_oxi_state_decorated_structure(structure)
        if not is_ox(ref_structure):
            a = BVAnalyzer()
            ref_structure = a.get_oxi_state_decorated_structure(ref_structure)

        if test_isostructural:
            m = StructureMatcher()
            mapping = m.get_best_electronegativity_anonymous_mapping(structure, ref_structure)
            if mapping is None:
                raise ValueError("Input structures do not match!")

        comp = structure.composition
        ref_comp = ref_structure.composition

        numerator = 0
        denominator = 0

        # Here, the 1/3 factor on the composition accounts for atomic
        # packing. We want the number per unit length.

        # TODO: AJ doesn't understand the (1/3). It would make sense to him
        # if you were doing atomic volume and not atomic radius
        for k, v in comp.items():
            numerator += k.ionic_radius * v ** (1 / 3)
        for k, v in ref_comp.items():
            denominator += k.ionic_radius * v ** (1 / 3)

        # The scaling factor is based on lengths. We apply a power of 3.
        return ref_structure.volume * (numerator / denominator) ** 3
Пример #10
0
    def test_electronegativity(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5)

        s1 = Structure.from_file(os.path.join(test_dir, "Na2Fe2PAsO4S4.json"))
        s2 = Structure.from_file(os.path.join(test_dir, "Na2Fe2PNO4Se4.json"))
        self.assertEqual(sm.get_best_electronegativity_anonymous_mapping(s1, s2),
                    {Element('S'): Element('Se'),
                     Element('As'): Element('N'),
                     Element('Fe'): Element('Fe'),
                     Element('Na'): Element('Na'),
                     Element('P'): Element('P'),
                     Element('O'): Element('O'),})
        self.assertEqual(len(sm.get_all_anonymous_mappings(s1, s2)), 2)

        # test include_dist
        dists = {Element('N'): 0, Element('P'): 0.0010725064}
        for mapping, d in sm.get_all_anonymous_mappings(s1, s2, include_dist=True):
            self.assertAlmostEqual(dists[mapping[Element('As')]], d)
Пример #11
0
    def test_electronegativity(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5)

        s1 = Structure.from_file(os.path.join(test_dir, "Na2Fe2PAsO4S4.json"))
        s2 = Structure.from_file(os.path.join(test_dir, "Na2Fe2PNO4Se4.json"))
        self.assertEqual(sm.get_best_electronegativity_anonymous_mapping(s1, s2),
                    {Element('S'): Element('Se'),
                     Element('As'): Element('N'),
                     Element('Fe'): Element('Fe'),
                     Element('Na'): Element('Na'),
                     Element('P'): Element('P'),
                     Element('O'): Element('O'),})
        self.assertEqual(len(sm.get_all_anonymous_mappings(s1, s2)), 2)

        # test include_dist
        dists = {Element('N'): 0, Element('P'): 0.0010725064}
        for mapping, d in sm.get_all_anonymous_mappings(s1, s2, include_dist=True):
            self.assertAlmostEqual(dists[mapping[Element('As')]], d)
Пример #12
0
    def predict(self, structure, ref_structure):
        """
        Given a structure, returns the predicted volume.

        Args:
            structure (Structure): structure w/unknown volume
            ref_structure (Structure): A reference structure with a similar
                structure but different species.
        Returns:
            a float value of the predicted volume
        """

        if self.check_isostructural:
            m = StructureMatcher()
            mapping = m.get_best_electronegativity_anonymous_mapping(structure, ref_structure)
            if mapping is None:
                raise ValueError("Input structures do not match!")

        if "ionic" in self.radii_type:
            try:
                # Use BV analyzer to determine oxidation states only if the
                # oxidation states are not already specified in the structure
                # and use_bv is true.
                if (not _is_ox(structure)) and self.use_bv:
                    a = BVAnalyzer()
                    structure = a.get_oxi_state_decorated_structure(structure)
                if (not _is_ox(ref_structure)) and self.use_bv:
                    a = BVAnalyzer()
                    ref_structure = a.get_oxi_state_decorated_structure(ref_structure)

                comp = structure.composition
                ref_comp = ref_structure.composition

                # Check if all the associated ionic radii are available.
                if any(k.ionic_radius is None for k in list(comp.keys())) or any(
                    k.ionic_radius is None for k in list(ref_comp.keys())
                ):
                    raise ValueError("Not all the ionic radii are available!")

                numerator = 0
                denominator = 0
                # Here, the 1/3 factor on the composition accounts for atomic
                # packing. We want the number per unit length.
                for k, v in comp.items():
                    numerator += k.ionic_radius * v ** (1 / 3)
                for k, v in ref_comp.items():
                    denominator += k.ionic_radius * v ** (1 / 3)

                return ref_structure.volume * (numerator / denominator) ** 3
            except Exception:
                warnings.warn("Exception occured. Will attempt atomic radii.")
                # If error occurs during use of ionic radii scheme, pass
                # and see if we can resolve it using atomic radii.
                pass

        if "atomic" in self.radii_type:
            comp = structure.composition
            ref_comp = ref_structure.composition
            # Here, the 1/3 factor on the composition accounts for atomic
            # packing. We want the number per unit length.
            numerator = 0
            denominator = 0
            for k, v in comp.items():
                numerator += k.atomic_radius * v ** (1 / 3)
            for k, v in ref_comp.items():
                denominator += k.atomic_radius * v ** (1 / 3)
            return ref_structure.volume * (numerator / denominator) ** 3

        raise ValueError("Cannot find volume scaling based on radii choices specified!")
Пример #13
0
    def predict(self, structure, ref_structure):
        """
        Given a structure, returns the predicted volume.
        Args:
            structure (Structure): structure w/unknown volume
            ref_structure (Structure): A reference structure with a similar
                structure but different species.
        Returns:
            a float value of the predicted volume
        """

        if self.check_isostructural:
            m = StructureMatcher()
            mapping = m.get_best_electronegativity_anonymous_mapping(
                structure, ref_structure)
            if mapping is None:
                raise ValueError("Input structures do not match!")

        if "ionic" in self.radii_type:
            try:
                # Use BV analyzer to determine oxidation states only if the
                # oxidation states are not already specified in the structure
                # and use_bv is true.
                if (not is_ox(structure)) and self.use_bv:
                    a = BVAnalyzer()
                    structure = a.get_oxi_state_decorated_structure(structure)
                if (not is_ox(ref_structure)) and self.use_bv:
                    a = BVAnalyzer()
                    ref_structure = a.get_oxi_state_decorated_structure(
                        ref_structure)

                comp = structure.composition
                ref_comp = ref_structure.composition

                # Check if all the associated ionic radii are available.
                if any([k.ionic_radius is None for k in list(comp.keys())]) or \
                        any([k.ionic_radius is None for k in
                             list(ref_comp.keys())]):
                    raise ValueError("Not all the ionic radii are available!")

                numerator = 0
                denominator = 0
                # Here, the 1/3 factor on the composition accounts for atomic
                # packing. We want the number per unit length.
                for k, v in comp.items():
                    numerator += k.ionic_radius * v ** (1 / 3)
                for k, v in ref_comp.items():
                    denominator += k.ionic_radius * v ** (1 / 3)

                return ref_structure.volume * (numerator / denominator) ** 3
            except Exception as ex:
                warnings.warn("Exception occured. Will attempt atomic radii.")
                # If error occurs during use of ionic radii scheme, pass
                # and see if we can resolve it using atomic radii.
                pass

        if "atomic" in self.radii_type:
            comp = structure.composition
            ref_comp = ref_structure.composition
            # Here, the 1/3 factor on the composition accounts for atomic
            # packing. We want the number per unit length.
            numerator = 0
            denominator = 0
            for k, v in comp.items():
                numerator += k.atomic_radius * v ** (1 / 3)
            for k, v in ref_comp.items():
                denominator += k.atomic_radius * v ** (1 / 3)
            return ref_structure.volume * (numerator / denominator) ** 3

        raise ValueError("Cannot find volume scaling based on radii choices "
                         "specified!")