Example #1
0
class BVAnalyzerTest(PymatgenTest):

    def setUp(self):
        self.analyzer = BVAnalyzer()

    def test_get_valence(self):
        s = Structure.from_file(os.path.join(test_dir, "LiMn2O4.json"))
        ans = [1, 1, 3, 3, 4, 4, -2, -2, -2, -2, -2, -2, -2, -2]
        self.assertEqual(self.analyzer.get_valences(s), ans)
        s = self.get_structure("LiFePO4")
        ans = [1, 1, 1, 1, 2, 2, 2, 2, 5, 5, 5, 5, -2, -2, -2, -2, -2, -2, -2,
               - 2, -2, -2, -2, -2, -2, -2, -2, -2]
        self.assertEqual(self.analyzer.get_valences(s), ans)
        s = self.get_structure("Li3V2(PO4)3")
        ans = [1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, -2, -2, -2, -2,
               - 2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
               - 2, -2, -2, -2]
        self.assertEqual(self.analyzer.get_valences(s), ans)
        s = Structure.from_file(os.path.join(test_dir, "Li4Fe3Mn1(PO4)4.json"))
        ans = [1, 1, 1, 1, 2, 2, 2, 2, 5, 5, 5, 5, -2, -2, -2, -2, -2, -2, -2,
               - 2, -2, -2, -2, -2, -2, -2, -2, -2]
        self.assertEqual(self.analyzer.get_valences(s), ans)
        s = self.get_structure("NaFePO4")
        ans = [1, 1, 1, 1, 2, 2, 2, 2, 5, 5, 5, 5, -2, -2, -2, -2, -2, -2, -2,
               - 2, -2, -2, -2, -2, -2, -2, -2, -2]
        self.assertEqual(self.analyzer.get_valences(s), ans)

    def test_get_oxi_state_structure(self):
        s = Structure.from_file(os.path.join(test_dir, "LiMn2O4.json"))
        news = self.analyzer.get_oxi_state_decorated_structure(s)
        self.assertIn(Specie("Mn", 3), news.composition.elements)
        self.assertIn(Specie("Mn", 4), news.composition.elements)
Example #2
0
    def _get_valences(self):
        """
        Computes ionic valences of elements for all sites in the structure.
        """
        try:
            bv = BVAnalyzer()
            self._structure = bv.get_oxi_state_decorated_structure(
                self._structure)
            valences = bv.get_valences(self._structure)
        except:
            try:
                bv = BVAnalyzer(symm_tol=0.0)
                self._structure = bv.get_oxi_state_decorated_structure(
                    self._structure)
                valences = bv.get_valences(self._structure)
            except:
                valences = [0] * self._structure.num_sites
                #raise

        #el = [site.specie.symbol for site in self._structure.sites]
        #el = [site.species_string for site in self._structure.sites]
        #el = [site.specie for site in self._structure.sites]
        #valence_dict = dict(zip(el, valences))
        #print valence_dict
        return valences
Example #3
0
    def __init__(self, defect):
        """
        Args:
            defect(Defect): pymatgen Defect object
        """
        self.defect = defect

        try:
            bv = BVAnalyzer()
            struct_valences = bv.get_valences(self.defect.bulk_structure)
            site_index = self.defect.bulk_structure.get_sites_in_sphere(
                self.defect.site.coords, 0.1, include_index=True)[0][2]
            def_site_valence = struct_valences[site_index]
        except Exception:  # sometimes valences cant be assigned
            def_site_valence = 0

        if isinstance(defect, Vacancy):
            self.charges = [-1 * def_site_valence]
        elif isinstance(defect, Substitution):
            #(minimize difference with host site specie)
            probable_chgs = [
                ox - def_site_valence
                for ox in self.defect.site.specie.oxidation_states
            ]
            self.charges = [min(probable_chgs, key=abs)]
        elif isinstance(defect, Interstitial):
            self.charges = [0]
        else:
            raise ValueError("Defect Type not recognized.")
Example #4
0
    def __init__(self, defect):
        """
        Args:
            defect(Defect): pymatgen Defect object
        """
        self.defect = defect

        try:
            bv = BVAnalyzer()
            struct_valences = bv.get_valences(self.defect.bulk_structure)
            site_index = self.defect.bulk_structure.get_sites_in_sphere(
                self.defect.site.coords, 0.1, include_index=True)[0][2]
            def_site_valence = struct_valences[site_index]
        except Exception:  # sometimes valences cant be assigned
            def_site_valence = 0

        if isinstance(defect, Vacancy):
            self.charges = [-1 * def_site_valence]
        elif isinstance(defect, Substitution):
            #(minimize difference with host site specie)
            probable_chgs = [ox - def_site_valence for ox in self.defect.site.specie.oxidation_states]
            self.charges = [min(probable_chgs, key=abs)]
        elif isinstance(defect, Interstitial):
            self.charges = [0]
        else:
            raise ValueError("Defect Type not recognized.")
Example #5
0
    def tersoff_potential(self, structure):
        """
        Generate the species, tersoff potential lines for an oxide structure

        Args:
            structure:
                pymatgen.core.structure.Structure
        """
        bv = BVAnalyzer()
        el = [site.species_string for site in structure.sites]
        valences = bv.get_valences(structure)
        el_val_dict = dict(zip(el, valences))

        gin = "species \n"
        qerfstring = "qerfc\n"

        for key in el_val_dict.keys():
            if key != "O" and el_val_dict[key] % 1 != 0:
                raise SystemError("Oxide has mixed valence on metal")
            specie_string = key + " core " + str(el_val_dict[key]) + "\n"
            gin += specie_string
            qerfstring += key + " " + key + " 0.6000 10.0000 \n"

        gin += "# noelectrostatics \n Morse \n"
        met_oxi_ters = Tersoff_pot().data
        for key in el_val_dict.keys():
            if key != "O":
                metal = key + "(" + str(int(el_val_dict[key])) + ")"
                ters_pot_str = met_oxi_ters[metal]
                gin += ters_pot_str

        gin += qerfstring
        return gin
Example #6
0
    def calc(self, item):
        s = Structure.from_dict(item["structure"])

        d = {
            "pymatgen_version": pymatgen_version,
            "successful": False,
            "bond_valence": {
                "structure": item["structure"],
                "method": None
            },
        }

        try:
            bva = BVAnalyzer()
            valences = bva.get_valences(s)
            possible_species = {
                str(Specie(s[idx].specie, oxidation_state=valence))
                for idx, valence in enumerate(valences)
            }

            d["successful"] = True
            s.add_oxidation_state_by_site(valences)

            d["bond_valence"] = {
                "possible_species": list(possible_species),
                "possible_valences": valences,
                "method": "BVAnalyzer",
                "structure": s.as_dict(),
            }

        except Exception as e:
            self.logger.error("BVAnalyzer failed with: {}".format(e))

            try:
                first_oxi_state_guess = s.composition.oxi_state_guesses(
                    max_sites=-50)[0]
                valences = [
                    first_oxi_state_guess[site.species_string] for site in s
                ]
                possible_species = {
                    str(Specie(el, oxidation_state=valence))
                    for el, valence in first_oxi_state_guess.items()
                }

                d["successful"] = True
                s.add_oxidation_state_by_site(valences)

                d["bond_valence"] = {
                    "possible_species": list(possible_species),
                    "possible_valences": valences,
                    "method": "oxi_state_guesses",
                    "structure": s.as_dict(),
                }
            except Exception as e:
                self.logger.error(
                    "Oxidation state guess failed with: {}".format(e))

        return d
Example #7
0
class BVAnalyzerTest(unittest.TestCase):
    def setUp(self):
        self.analyzer = BVAnalyzer()

    def test_get_valence(self):
        parser = CifParser(os.path.join(test_dir, "LiMn2O4.cif"))
        s = parser.get_structures()[0]
        ans = [1, 1, 3, 3, 4, 4, -2, -2, -2, -2, -2, -2, -2, -2]
        self.assertEqual(self.analyzer.get_valences(s), ans)
        parser = CifParser(os.path.join(test_dir, "LiFePO4.cif"))
        s = parser.get_structures()[0]
        ans = [
            1, 1, 1, 1, 2, 2, 2, 2, 5, 5, 5, 5, -2, -2, -2, -2, -2, -2, -2, -2,
            -2, -2, -2, -2, -2, -2, -2, -2
        ]
        self.assertEqual(self.analyzer.get_valences(s), ans)
        parser = CifParser(os.path.join(test_dir, "Li3V2(PO4)3.cif"))
        s = parser.get_structures()[0]
        ans = [
            1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, -2, -2, -2, -2, -2,
            -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
            -2, -2
        ]
        self.assertEqual(self.analyzer.get_valences(s), ans)
        parser = CifParser(os.path.join(test_dir, "Li4Fe3Mn1(PO4)4.cif"))
        s = parser.get_structures()[0]
        ans = [
            1, 1, 1, 1, 2, 2, 2, 2, 5, 5, 5, 5, -2, -2, -2, -2, -2, -2, -2, -2,
            -2, -2, -2, -2, -2, -2, -2, -2
        ]
        self.assertEqual(self.analyzer.get_valences(s), ans)
        parser = CifParser(os.path.join(test_dir, "NaFePO4.cif"))
        s = parser.get_structures()[0]
        ans = [
            1, 1, 1, 1, 2, 2, 2, 2, 5, 5, 5, 5, -2, -2, -2, -2, -2, -2, -2, -2,
            -2, -2, -2, -2, -2, -2, -2, -2
        ]
        self.assertEqual(self.analyzer.get_valences(s), ans)

    def test_get_oxi_state_structure(self):
        parser = CifParser(os.path.join(test_dir, "LiMn2O4.cif"))
        s = parser.get_structures()[0]
        news = self.analyzer.get_oxi_state_decorated_structure(s)
        self.assertIn(Specie("Mn", 3), news.composition.elements)
        self.assertIn(Specie("Mn", 4), news.composition.elements)
Example #8
0
 def _get_valences(self):
     """
     Computes ionic valences of elements for all sites in the structure.
     """
     bv = BVAnalyzer()
     valences = bv.get_valences(self._structure)
     el = [site.species_string for site in self.structure.sites]
     valence_dict = dict(zip(el, valences))
     return valence_dict
Example #9
0
    def _get_valences(self):
        """
        Computes ionic valences of elements for all sites in the structure.
        """
        bv = BVAnalyzer()
        self._structure = bv.get_oxi_state_decorated_structure(self._structure)
        try:
            valences = bv.get_valences(self._structure)
        except:
            try:
                valences = bv.get_valences(self._structure, symm_tol=0.0)
            except:
                raise

        #print valences
        #el = [site.specie.symbol for site in self._structure.sites]
        #el = [site.species_string for site in self._structure.sites]
        #el = [site.specie for site in self._structure.sites]
        #valence_dict = dict(zip(el, valences))
        #print valence_dict
        return valences
Example #10
0
 def setUp(self):
     mgo_latt = [[4.212, 0, 0], [0, 4.212, 0], [0, 0, 4.212]]
     mgo_specie = ["Mg", 'O'] * 4
     mgo_frac_cord = [[0, 0, 0], [0.5, 0, 0], [0.5, 0.5, 0], [0, 0.5, 0],
                      [0.5, 0, 0.5], [0, 0, 0.5], [0, 0.5, 0.5],
                      [0.5, 0.5, 0.5]]
     self.mgo_uc = Structure(mgo_latt, mgo_specie, mgo_frac_cord, True,
                             True)
     bv = BVAnalyzer()
     val = bv.get_valences(self.mgo_uc)
     el = [site.species_string for site in self.mgo_uc.sites]
     self.val_dict = dict(zip(el, val))
Example #11
0
    def setUp(self):
        filepath = os.path.join(test_dir, 'POSCAR')
        p = Poscar.from_file(filepath)
        self.structure = p.structure
        bv = BVAnalyzer()
        valences = bv.get_valences(self.structure)
        el = [site.species_string for site in self.structure.sites]
        valence_dict = dict(zip(el, valences))
        self.rad_dict = {}
        for k, v in valence_dict.items():
            self.rad_dict[k] = float(Specie(k, v).ionic_radius)

        assert len(self.rad_dict) == len(self.structure.composition)
Example #12
0
 def setUp(self):
     filepath1 = os.path.join(PymatgenTest.TEST_FILES_DIR, "Li2O.cif")
     p = CifParser(filepath1).get_structures(False)[0]
     bv = BVAnalyzer()
     valences = bv.get_valences(p)
     el = [site.species_string for site in p.sites]
     val_dict = dict(zip(el, valences))
     self._radii = {}
     for k, v in val_dict.items():
         k1 = re.sub(r"[1-9,+,\-]", "", k)
         self._radii[k1] = float(Species(k1, v).ionic_radius)
     p.remove(0)
     self._vac_struct = p
Example #13
0
    def setUp(self):
        filepath = os.path.join(test_dir, 'POSCAR')
        p = Poscar.from_file(filepath)
        self.structure = p.structure
        bv = BVAnalyzer()
        valences = bv.get_valences(self.structure)
        el = [site.species_string for site in self.structure.sites]
        valence_dict = dict(zip(el, valences))
        self.rad_dict = {}
        for k, v in valence_dict.items():
            self.rad_dict[k] = Specie(k,v).ionic_radius

        assert len(self.rad_dict) == len(self.structure.composition)
Example #14
0
 def setUp(self):
     filepath1 = os.path.join(test_dir, 'Li2O.cif')
     p = CifParser(filepath1).get_structures(False)[0]
     bv = BVAnalyzer()
     valences = bv.get_valences(p)
     el = [site.species_string for site in p.sites]
     val_dict = dict(zip(el, valences))
     self._radii = {}
     for k,v in val_dict.items():
         k1 = re.sub('[1-9,+,\-]', '', k)
         self._radii[k] = Specie(k1, v).ionic_radius
     p.remove(0)
     self._vac_struct = p
Example #15
0
 def setUp(self):
     filepath1 = os.path.join(test_dir, 'Li2O.cif')
     p = CifParser(filepath1).get_structures(False)[0]
     bv = BVAnalyzer()
     valences = bv.get_valences(p)
     el = [site.species_string for site in p.sites]
     val_dict = dict(zip(el, valences))
     self._radii = {}
     for k, v in val_dict.items():
         k1 = re.sub(r'[1-9,+,\-]', '', k)
         self._radii[k1] = float(Specie(k1, v).ionic_radius)
     p.remove(0)
     self._vac_struct = p
Example #16
0
class BVAnalyzerTest(unittest.TestCase):

    def setUp(self):
        self.analyzer = BVAnalyzer()

    def test_get_valence(self):
        parser = CifParser(os.path.join(test_dir, "LiMn2O4.cif"))
        s = parser.get_structures()[0]
        ans = [1, 1, 3, 3, 4, 4, -2, -2, -2, -2, -2, -2, -2, -2]
        self.assertEqual(self.analyzer.get_valences(s), ans)
        parser = CifParser(os.path.join(test_dir, "LiFePO4.cif"))
        s = parser.get_structures()[0]
        ans = [1, 1, 1, 1, 2, 2, 2, 2, 5, 5, 5, 5, -2, -2, -2, -2, -2, -2, -2,
               - 2, -2, -2, -2, -2, -2, -2, -2, -2]
        self.assertEqual(self.analyzer.get_valences(s), ans)
        parser = CifParser(os.path.join(test_dir, "Li3V2(PO4)3.cif"))
        s = parser.get_structures()[0]
        ans = [1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, -2, -2, -2, -2,
               - 2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
               - 2, -2, -2, -2]
        self.assertEqual(self.analyzer.get_valences(s), ans)
        parser = CifParser(os.path.join(test_dir, "Li4Fe3Mn1(PO4)4.cif"))
        s = parser.get_structures()[0]
        ans = [1, 1, 1, 1, 2, 2, 2, 2, 5, 5, 5, 5, -2, -2, -2, -2, -2, -2, -2,
               - 2, -2, -2, -2, -2, -2, -2, -2, -2]
        self.assertEqual(self.analyzer.get_valences(s), ans)
        parser = CifParser(os.path.join(test_dir, "NaFePO4.cif"))
        s = parser.get_structures()[0]
        ans = [1, 1, 1, 1, 2, 2, 2, 2, 5, 5, 5, 5, -2, -2, -2, -2, -2, -2, -2,
               - 2, -2, -2, -2, -2, -2, -2, -2, -2]
        self.assertEqual(self.analyzer.get_valences(s), ans)

    def test_get_oxi_state_structure(self):
        parser = CifParser(os.path.join(test_dir, "LiMn2O4.cif"))
        s = parser.get_structures()[0]
        news = self.analyzer.get_oxi_state_decorated_structure(s)
        self.assertIn(Specie("Mn", 3), news.composition.elements)
        self.assertIn(Specie("Mn", 4), news.composition.elements)
Example #17
0
 def setUp(self):
     filepath = os.path.join(test_dir, 'POSCAR')
     p = Poscar.from_file(filepath)
     self.structure = p.structure
     bv = BVAnalyzer()
     self.structure = bv.get_oxi_state_decorated_structure(self.structure)
     valences = bv.get_valences(self.structure)
     radii = []
     for i in range(len(valences)):
         el = self.structure.sites[i].specie.symbol
         radius = Specie(el, valences[i]).ionic_radius
         radii.append(radius)
     el = [site.species_string for site in self.structure.sites]
     self.rad_dict = dict(zip(el, radii))
     for el in self.rad_dict.keys():
         print((el, self.rad_dict[el].real))
Example #18
0
    def _get_valences(self):
        """
        Computes ionic valences of elements for all sites in the structure.
        """
        bv = BVAnalyzer()
        try:
            valences = bv.get_valences(self._structure)
        except:
            err_str = "BVAnalyzer failed. The defect effective charge, and"
            err_str += " volume and surface area may not work"
            print err_str
            raise LookupError()

        el = [site.species_string for site in self.structure.sites]
        valence_dict = dict(zip(el, valences))
        return valence_dict
Example #19
0
    def _get_valences(self):
        """
        Computes ionic valences of elements for all sites in the structure.
        """
        bv = BVAnalyzer()
        try:
            valences = bv.get_valences(self._structure)
        except:
            err_str = "BVAnalyzer failed. The defect effective charge, and"
            err_str += " volume and surface area may not work"
            print err_str
            raise LookupError()

        el = [site.species_string for site in self.structure.sites]
        valence_dict = dict(zip(el, valences))
        return valence_dict
    def setUp(self):
        with open("mp-7000.json", "r") as f:
            dict_lse = json.load(f)
        lse = LightStructureEnvironments.from_dict(dict_lse)
        struct = lse.structure
        bva = BVAnalyzer()
        valences = bva.get_valences(structure=struct)
        lgf = LocalGeometryFinder()
        lgf.setup_structure(structure=struct)
        se = lgf.compute_structure_environments(maximum_distance_factor=1.41, only_cations=False, valences=valences)
        strategy = MultiWeightsChemenvStrategy.stats_article_weights_parameters()
        self.lse = LightStructureEnvironments.from_structure_environments(strategy=strategy, structure_environments=se)

        with open("mp-5634.json", "r") as f:
            dict_lse2 = json.load(f)
        self.lse2 = LightStructureEnvironments.from_dict(dict_lse2)
Example #21
0
 def setUp(self):
     filepath = os.path.join(test_dir, 'POSCAR')
     p = Poscar.from_file(filepath)
     self.structure = p.structure
     bv = BVAnalyzer()
     self.structure = bv.get_oxi_state_decorated_structure(self.structure)
     valences = bv.get_valences(self.structure)
     radii = []
     for i in range(len(valences)):
         el = self.structure.sites[i].specie.symbol
         radius = Specie(el, valences[i]).ionic_radius
         radii.append(radius)
     el = [site.species_string for site in self.structure.sites]
     self.rad_dict = dict(zip(el, radii))
     for el in self.rad_dict.keys():
         print((el, self.rad_dict[el].real))
Example #22
0
    def __init__(self, structure, include_bv_charge=False):
        """
        Initializes a Vacancy Generator
        Args:
            structure(Structure): pymatgen structure object
        """
        self.structure = structure
        self.include_bv_charge = include_bv_charge

        # Find equivalent site list
        sga = SpacegroupAnalyzer(self.structure)
        self.symm_structure = sga.get_symmetrized_structure()
        self.equiv_site_seq = list(self.symm_structure.equivalent_sites)

        self.struct_valences = None
        if self.include_bv_charge:
            bv = BVAnalyzer()
            self.struct_valences = bv.get_valences(self.structure)
Example #23
0
    def __init__(self, structure, include_bv_charge=False):
        """
        Initializes a Vacancy Generator
        Args:
            structure(Structure): pymatgen structure object
        """
        self.structure = structure
        self.include_bv_charge = include_bv_charge

        # Find equivalent site list
        sga = SpacegroupAnalyzer(self.structure)
        self.symm_structure = sga.get_symmetrized_structure()
        self.equiv_site_seq = list(self.symm_structure.equivalent_sites)

        self.struct_valences = None
        if self.include_bv_charge:
            bv = BVAnalyzer()
            self.struct_valences = bv.get_valences(self.structure)
Example #24
0
    def get_atomic_radii(self):
        if not self.pymatgen_radii:
            return None

        try:
            bv = BVAnalyzer()
            valences = bv.get_valences(self._structure)
            elements = [site.species_string for site in self._structure.sites]

            valence_dict = dict(zip(elements, valences))
            radii = {}
            for k, v in valence_dict.items():
                radii[k] = float(Specie(k, v).ionic_radius)

        except (ValueError, TypeError) as e:
            radii = None

        return radii
Example #25
0
    def get_valences(self):
        """
        Uses Pymatgen to obtain likely valence states of every element in structure

        Returns
            vals: dictionary of average valence state for every element in composition
        """

        struct = self.structure
        bv = BVAnalyzer()
        try:
            valences = bv.get_valences(struct)
            struct = bv.get_oxi_state_decorated_structure(struct)
        except:
            return None

        if isinstance(valences[0], list):
            valences = [item for sublist in valences for item in sublist]

        stoich = defaultdict(int)
        for site in struct.as_dict()['sites']:
            elem = site['species'][0]['element']
            stoich[elem] += 1

        vals = {}

        for spec in stoich.keys():
            vals[spec] = 0.0

        for atom in range(len(struct)):
            try:
                vals[struct.as_dict()['sites'][atom]['species'][0]
                     ['element']] += valences[atom]
            except Exception as e:
                print("Trouble with {}".format(struct.formula))
                print('Do you have partial occupancies?')
                return None

        for spec in vals:
            vals[spec] = vals[spec] / stoich[spec]
            vals[spec] = int(round(vals[spec]))

        return vals
Example #26
0
    def get_coordsites_min_max_charge(self, n):
        """
        Minimum and maximum charge of sites surrounding the vacancy site.

        Args:
            n: Index of vacancy list
        """
        bv = BVAnalyzer()
        struct_valences = bv.get_valences(self._structure)
        coordinated_site_valences = []

        def _get_index(site):
            for i in range(len(self._structure.sites)):
                if site.is_periodic_image(self._structure.sites[i]):
                    return i
            raise ValueError("Site not found")

        for site in self._defect_coord_sites[n]:
            ind = _get_index(site)
            coordinated_site_valences.append(struct_valences[ind])
        coordinated_site_valences.sort()
        return coordinated_site_valences[0], coordinated_site_valences[-1]
Example #27
0
    def get_coordsites_min_max_charge(self, n):
        """
        Minimum and maximum charge of sites surrounding the vacancy site.

        Args:
            n: Index of vacancy list
        """
        bv = BVAnalyzer()
        struct_valences = bv.get_valences(self._structure)
        coordinated_site_valences = []

        def _get_index(site):
            for i in range(len(self._structure.sites)):
                if site.is_periodic_image(self._structure.sites[i]):
                    return i
            raise ValueError("Site not found")

        for site in self._defect_coord_sites[n]:
            ind = _get_index(site)
            coordinated_site_valences.append(struct_valences[ind])
        coordinated_site_valences.sort()
        return coordinated_site_valences[0], coordinated_site_valences[-1]
Example #28
0
    def process_item(self, item):
        s = Structure.from_dict(item['structure'])
        try:
            bva = BVAnalyzer()
            valences = bva.get_valences(s)
            possible_species = {
                str(Specie(s[idx].specie, oxidation_state=valence))
                for idx, valence in enumerate(valences)
            }

            method = "BVAnalyzer"
        except ValueError:
            try:
                first_oxi_state_guess = s.composition.oxi_state_guesses()[0]
                valences = [
                    first_oxi_state_guess[site.species_string] for site in s
                ]
                possible_species = {
                    str(Specie(el, oxidation_state=valence))
                    for el, valence in first_oxi_state_guess.items()
                }
                method = "oxi_state_guesses"
            except:
                return {
                    "task_id": item['task_id'],
                    "pymatgen_version": pymatgen_version,
                    "successful": False
                }

        return {
            "task_id": item['task_id'],
            "possible_species": list(possible_species),
            "possible_valences": valences,
            "method": method,
            "pymatgen_version": pymatgen_version,
            "successful": True
        }
def Calc_Ewald(pmg_struct, formal_val=[]):
    """
    input: pmg_struct: pymatgen structure
           formal_val: list - list of valence for each atom

    TBD: use input formal valence list to decorate the structure
    """
    # GET valence list
    if len(formal_val)==0:
        bv_analyzer=BVAnalyzer(max_radius=4) #max_radius default is 4
        formal_val=bv_analyzer.get_valences(pmg_struct)

    # default for cutoff is set to None
    real_cutoff = None
    rec_cutoff = None

    # Oxidation states are decorated automatically.  
    decorated_struct = bv_analyzer.get_oxi_state_decorated_structure(pmg_struct)
    NUM_sites=pmg_struct.num_sites
    
    # Per atom
    ewald_per_atom=1/NUM_sites*EwaldSummation(decorated_struct,
        real_space_cut=real_cutoff, recip_space_cut=rec_cutoff).total_energy
    return ewald_per_atom
Example #30
0
    def buckingham_potential(structure, val_dict=None):
        """
        Generate species, buckingham, and spring options for an oxide structure
        using the parameters in default libraries.

        Ref:
            1. G.V. Lewis and C.R.A. Catlow, J. Phys. C: Solid State Phys.,
               18, 1149-1161 (1985)
            2. T.S.Bush, J.D.Gale, C.R.A.Catlow and P.D. Battle,
               J. Mater Chem., 4, 831-837 (1994)

        Args:
            structure: pymatgen.core.structure.Structure
            val_dict (Needed if structure is not charge neutral): {El:valence}
                dict, where El is element.
        """
        if not val_dict:
            try:
                # If structure is oxidation state decorated, use that first.
                el = [site.specie.symbol for site in structure]
                valences = [site.specie.oxi_state for site in structure]
                val_dict = dict(zip(el, valences))
            except AttributeError:
                bv = BVAnalyzer()
                el = [site.specie.symbol for site in structure]
                valences = bv.get_valences(structure)
                val_dict = dict(zip(el, valences))

        # Try bush library first
        bpb = BuckinghamPotential("bush")
        bpl = BuckinghamPotential("lewis")
        gin = ""
        for key in val_dict.keys():
            use_bush = True
            el = re.sub(r"[1-9,+,\-]", "", key)
            if el not in bpb.species_dict.keys():
                use_bush = False
            elif val_dict[key] != bpb.species_dict[el]["oxi"]:
                use_bush = False
            if use_bush:
                gin += "species \n"
                gin += bpb.species_dict[el]["inp_str"]
                gin += "buckingham \n"
                gin += bpb.pot_dict[el]
                gin += "spring \n"
                gin += bpb.spring_dict[el]
                continue

            # Try lewis library next if element is not in bush
            # use_lewis = True
            if el != "O":  # For metals the key is "Metal_OxiState+"
                k = el + "_" + str(int(val_dict[key])) + "+"
                if k not in bpl.species_dict.keys():
                    # use_lewis = False
                    raise GulpError(f"Element {k} not in library")
                gin += "species\n"
                gin += bpl.species_dict[k]
                gin += "buckingham\n"
                gin += bpl.pot_dict[k]
            else:
                gin += "species\n"
                k = "O_core"
                gin += bpl.species_dict[k]
                k = "O_shel"
                gin += bpl.species_dict[k]
                gin += "buckingham\n"
                gin += bpl.pot_dict[key]
                gin += "spring\n"
                gin += bpl.spring_dict[key]
        return gin
Example #31
0
    def run(self, sn):
        """
        Args:
            sn (SiteNetwork)
        Returns:
            ``sn``, with type information.
        """
        # -- Determine local environments
        # Get an ASE structure with a single mobile site that we'll move around
        if sn.n_sites == 0:
            logger.warning("Site network had no sites.")
            return sn
        site_struct, site_species = sn[0:1].get_structure_with_sites()
        pymat_struct = AseAtomsAdaptor.get_structure(site_struct)
        lgf = cgf.LocalGeometryFinder()
        site_atom_index = len(site_struct) - 1

        coord_envs = []
        vertices = []

        valences = 'undefined'
        if self._guess_ionic_bonds:
            sim_struct = AseAtomsAdaptor.get_structure(sn.structure)
            valences = np.zeros(shape = len(site_struct), dtype = np.int)
            bv = BVAnalyzer()
            try:
                struct_valences = np.asarray(bv.get_valences(sim_struct))
            except ValueError as ve:
                logger.warning("Failed to compute bond valences: %s" % ve)
            else:
                valences = np.zeros(shape = len(site_struct), dtype = np.int)
                valences[:site_atom_index] = struct_valences[sn.static_mask]
                mob_val = struct_valences[sn.mobile_mask]
                if np.any(mob_val != mob_val[0]):
                    logger.warning("Mobile atom estimated valences (%s) not uniform; arbitrarily taking first." % mob_val)
                valences[site_atom_index] = mob_val[0]
            finally:
                valences = list(valences)

        logger.info("Running site coordination environment analysis...")
        # Do this once.
        # __init__ here defaults to disabling structure refinement, so all this
        # method is doing is making a copy of the structure and setting some
        # variables to None.
        lgf.setup_structure(structure = pymat_struct)

        for site in tqdm(range(sn.n_sites), desc = 'Site'):
            # Update the position of the site
            lgf.structure[site_atom_index].coords = sn.centers[site]
            # Compute structure environments for the site
            struct_envs = lgf.compute_structure_environments(
                only_indices = [site_atom_index],
                valences = valences,
                additional_conditions = [AdditionalConditions.ONLY_ANION_CATION_BONDS],
                **self._kwargs
            )
            struct_envs = LightStructureEnvironments.from_structure_environments(
                strategy = cgf.LocalGeometryFinder.DEFAULT_STRATEGY,
                structure_environments = struct_envs
            )
            # Store the results
            # We take the first environment for each site since it's the most likely
            this_site_envs = struct_envs.coordination_environments[site_atom_index]
            if len(this_site_envs) > 0:
                coord_envs.append(this_site_envs[0])
                vertices.append(
                    [n['index'] for n in struct_envs.neighbors_sets[site_atom_index][0].neighb_indices_and_images]
                )
            else:
                coord_envs.append({'ce_symbol' : 'BAD:0', 'ce_fraction' : 0.})
                vertices.append([])

        del lgf
        del struct_envs

        # -- Postprocess
        # TODO: allow user to ask for full fractional breakdown
        str_coord_environments = [env['ce_symbol'] for env in coord_envs]
        # The closer to 1 this is, the better
        site_type_confidences = np.array([env['ce_fraction'] for env in coord_envs])
        coordination_numbers = np.array([int(env['ce_symbol'].split(':')[1]) for env in coord_envs])
        assert np.all(coordination_numbers == [len(v) for v in vertices])

        typearr = str_coord_environments if self._full_chemenv_site_types else coordination_numbers
        unique_envs = list(set(typearr))
        site_types = np.array([unique_envs.index(t) for t in typearr])

        n_types = len(unique_envs)
        logger.info(("Type         " + "{:<8}" * n_types).format(*unique_envs))
        logger.info(("# of sites   " + "{:<8}" * n_types).format(*np.bincount(site_types)))

        sn.site_types = site_types
        sn.vertices = vertices
        sn.add_site_attribute("coordination_environments", str_coord_environments)
        sn.add_site_attribute("site_type_confidences", site_type_confidences)
        sn.add_site_attribute("coordination_numbers", coordination_numbers)

        return sn
Example #32
0
    def buckingham_potential(self, structure, val_dict=None):
        """
        Generate species, buckingham, and spring options for an oxide structure
        using the parameters in default libraries.

        Ref:
            1. G.V. Lewis and C.R.A. Catlow, J. Phys. C: Solid State Phys.,
               18, 1149-1161 (1985)
            2. T.S.Bush, J.D.Gale, C.R.A.Catlow and P.D. Battle,
               J. Mater Chem., 4, 831-837 (1994)

        Args:
            structure:
                pymatgen.core.structure.Structure
            val_dict (Needed if structure is not charge neutral)
                El:valence dictionary, where El is element.
        """
        if not val_dict:
            bv = BVAnalyzer()
            el = [site.species_string for site in structure.sites]
            valences = bv.get_valences(structure)
            val_dict = dict(zip(el, valences))

        #Try bush library first
        bpb = BuckinghamPotBush()
        bpl = BuckinghamPotLewis()
        gin = ""
        for key in val_dict.keys():
            use_bush = True
            el = re.sub('[1-9,+,\-]', '', key)
            if el not in bpb.species_dict.keys():
                use_bush = False
            elif val_dict[key] != bpb.species_dict[el]['oxi']:
                use_bush = False
            if use_bush:
                gin += "species \n"
                gin += bpb.species_dict[el]['inp_str']
                gin += "buckingham \n"
                gin += bpb.pot_dict[el]
                gin += "spring \n"
                gin += bpb.spring_dict[el]
                continue

            #Try lewis library next if element is not in bush
            #use_lewis = True
            if el != "O":  # For metals the key is "Metal_OxiState+"
                k = el + '_' + str(int(val_dict[key])) + '+'
                if k not in bpl.species_dict.keys():
                    #use_lewis = False
                    raise GulpError("Element {} not in library".format(k))
                gin += "species\n"
                gin += bpl.species_dict[k]
                gin += "buckingham\n"
                gin += bpl.pot_dict[k]
            else:
                gin += "species\n"
                k = "O_core"
                gin += bpl.species_dict[k]
                k = "O_shel"
                gin += bpl.species_dict[k]
                gin += "buckingham\n"
                gin += bpl.pot_dict[key]
                gin += 'spring\n'
                gin += bpl.spring_dict[key]
        return gin
Example #33
0
    def run_task(self, fw_spec):
        logging.basicConfig(
            filename='chemenv_structure_environments.log',
            format='%(levelname)s:%(module)s:%(funcName)s:%(message)s',
            level=logging.DEBUG)
        lgf = LocalGeometryFinder()
        lgf.setup_parameters(
            centering_type='centroid',
            include_central_site_in_centroid=True,
            structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE)
        if 'chemenv_parameters' in fw_spec:
            for param, value in fw_spec['chemenv_parameters'].items():
                lgf.setup_parameter(param, value)
        identifier = fw_spec['identifier']
        if 'structure' in fw_spec:
            structure = fw_spec['structure']
        else:
            if identifier[
                    'source'] == 'MaterialsProject' and 'material_id' in identifier:
                if not 'mapi_key' in fw_spec:
                    raise ValueError(
                        'The mapi_key should be provided to get the structure from the Materials Project'
                    )
                a = MPRester(fw_spec['mapi_key'])
                structure = a.get_structure_by_material_id(
                    identifier['material_id'])
            else:
                raise ValueError(
                    'Either structure or identifier with source = MaterialsProject and material_id '
                    'should be provided')

        info = {}
        # Compute the structure environments
        lgf.setup_structure(structure)
        if 'valences' in fw_spec:
            valences = fw_spec['valences']
        else:
            try:
                bva = BVAnalyzer()
                valences = bva.get_valences(structure=structure)
                info['valences'] = {'origin': 'BVAnalyzer'}
            except:
                valences = 'undefined'
                info['valences'] = {'origin': 'None'}
        excluded_atoms = None
        if 'excluded_atoms' in fw_spec:
            excluded_atoms = fw_spec['excluded_atoms']

        se = lgf.compute_structure_environments(only_cations=False,
                                                valences=valences,
                                                excluded_atoms=excluded_atoms)

        # Write to json file
        if 'json_file' in fw_spec:
            json_file = fw_spec['json_file']
        else:
            json_file = 'structure_environments.json'
        f = open(json_file, 'w')
        json.dump(se.as_dict(), f)
        f.close()

        # Save to database
        if 'mongo_database' in fw_spec:
            database = fw_spec['mongo_database']
            entry = {
                'identifier':
                identifier,
                'elements':
                [elmt.symbol for elmt in structure.composition.elements],
                'nelements':
                len(structure.composition.elements),
                'pretty_formula':
                structure.composition.reduced_formula,
                'nsites':
                len(structure)
            }

            saving_option = fw_spec['saving_option']
            if saving_option == 'gridfs':
                gridfs_msonables = {
                    'structure': structure,
                    'structure_environments': se
                }
            elif saving_option == 'storefile':
                gridfs_msonables = None
                if 'se_prefix' in fw_spec:
                    se_prefix = fw_spec['se_prefix']
                    if not se_prefix.isalpha():
                        raise ValueError(
                            'Prefix for structure_environments file is "{}" '
                            'while it should be alphabetic'.format(se_prefix))
                else:
                    se_prefix = ''
                if se_prefix:
                    se_rfilename = '{}_{}.json'.format(
                        se_prefix, fw_spec['storefile_basename'])
                else:
                    se_rfilename = '{}.json'.format(
                        fw_spec['storefile_basename'])
                se_rfilepath = '{}/{}'.format(fw_spec['storefile_dirpath'],
                                              se_rfilename)
                storage_server = fw_spec['storage_server']
                storage_server.put(localpath=json_file,
                                   remotepath=se_rfilepath,
                                   overwrite=True,
                                   makedirs=False)
                entry['structure_environments_file'] = se_rfilepath
            else:
                raise ValueError(
                    'Saving option is "{}" while it should be '
                    '"gridfs" or "storefile"'.format(saving_option))
            criteria = {'identifier': identifier}
            if database.collection.find(criteria).count() == 1:
                database.update_entry(query=criteria,
                                      entry_update=entry,
                                      gridfs_msonables=gridfs_msonables)
            else:
                database.insert_entry(entry=entry,
                                      gridfs_msonables=gridfs_msonables)
Example #34
0
    def run_task(self, fw_spec):
        logging.basicConfig(filename='chemenv_structure_environments.log',
                            format='%(levelname)s:%(module)s:%(funcName)s:%(message)s',
                            level=logging.DEBUG)
        lgf = LocalGeometryFinder()
        lgf.setup_parameters(centering_type='centroid', include_central_site_in_centroid=True,
                             structure_refinement=lgf.STRUCTURE_REFINEMENT_NONE)
        if 'chemenv_parameters' in fw_spec:
            for param, value in fw_spec['chemenv_parameters'].items():
                lgf.setup_parameter(param, value)
        identifier = fw_spec['identifier']
        if 'structure' in fw_spec:
            structure = fw_spec['structure']
        else:
            if identifier['source'] == 'MaterialsProject' and 'material_id' in identifier:
                if not 'mapi_key' in fw_spec:
                    raise ValueError('The mapi_key should be provided to get the structure from the Materials Project')
                # FIXME: Use MPRester from pymatgen
                from pymatgen.matproj.rest import MPRester
                a = MPRester(fw_spec['mapi_key'])
                structure = a.get_structure_by_material_id(identifier['material_id'])
            else:
                raise ValueError('Either structure or identifier with source = MaterialsProject and material_id '
                                 'should be provided')

        info = {}
        # Compute the structure environments
        lgf.setup_structure(structure)
        if 'valences' in fw_spec:
            valences = fw_spec['valences']
        else:
            try:
                bva = BVAnalyzer()
                valences = bva.get_valences(structure=structure)
                info['valences'] = {'origin': 'BVAnalyzer'}
            except:
                valences = 'undefined'
                info['valences'] = {'origin': 'None'}
        excluded_atoms = None
        if 'excluded_atoms' in fw_spec:
            excluded_atoms = fw_spec['excluded_atoms']

        se = lgf.compute_structure_environments(only_cations=False, valences=valences, excluded_atoms=excluded_atoms)

        # Write to json file
        if 'json_file' in fw_spec:
            json_file = fw_spec['json_file']
        else:
            json_file = 'structure_environments.json'
        f = open(json_file, 'w')
        json.dump(se.as_dict(), f)
        f.close()

        # Save to database
        if 'mongo_database' in fw_spec:
            database = fw_spec['mongo_database']
            entry = {'identifier': identifier,
                     'elements': [elmt.symbol for elmt in structure.composition.elements],
                     'nelements': len(structure.composition.elements),
                     'pretty_formula': structure.composition.reduced_formula,
                     'nsites': len(structure)
                     }

            saving_option = fw_spec['saving_option']
            if saving_option == 'gridfs':
                gridfs_msonables = {'structure': structure,
                                    'structure_environments': se}
            elif saving_option == 'storefile':
                gridfs_msonables = None
                if 'se_prefix' in fw_spec:
                    se_prefix = fw_spec['se_prefix']
                    if not se_prefix.isalpha():
                        raise ValueError('Prefix for structure_environments file is "{}" '
                                         'while it should be alphabetic'.format(se_prefix))
                else:
                    se_prefix = ''
                if se_prefix:
                    se_rfilename = '{}_{}.json'.format(se_prefix, fw_spec['storefile_basename'])
                else:
                    se_rfilename = '{}.json'.format(fw_spec['storefile_basename'])
                se_rfilepath = '{}/{}'.format(fw_spec['storefile_dirpath'], se_rfilename)
                storage_server = fw_spec['storage_server']
                storage_server.put(localpath=json_file, remotepath=se_rfilepath, overwrite=True, makedirs=False)
                entry['structure_environments_file'] = se_rfilepath
            else:
                raise ValueError('Saving option is "{}" while it should be '
                                 '"gridfs" or "storefile"'.format(saving_option))
            criteria = {'identifier': identifier}
            if database.collection.find(criteria).count() == 1:
                database.update_entry(query=criteria, entry_update=entry,
                                      gridfs_msonables=gridfs_msonables)
            else:
                database.insert_entry(entry=entry, gridfs_msonables=gridfs_msonables)
Example #35
0
    def __init__(
        self,
        are_coops=False,
        filename_ICOHP=None,
        valences=None,
        limits=None,
        structure=None,
        additional_condition=0,
        only_bonds_to=None,
        perc_strength_ICOHP=0.15,
        valences_from_charges=False,
        filename_CHARGE=None,
    ):
        """

        Args:
            are_coops: (Bool) if True, the file is a ICOOPLIST.lobster and not a ICOHPLIST.lobster; only tested for
            ICOHPLIST.lobster so far
            filename_ICOHP: (str) Path to ICOOPLIST.lobster
            valences: (list of integers/floats) gives valence/charge for each element
            limits: limit to decide which ICOHPs should be considered
            structure: (Structure Object) typically constructed by: Structure.from_file("POSCAR") (Structure object
            from pymatgen.core.structure)
            additional_condition:   Additional condition that decides which kind of bonds will be considered
                                    NO_ADDITIONAL_CONDITION = 0
                                    ONLY_ANION_CATION_BONDS = 1
                                    NO_ELEMENT_TO_SAME_ELEMENT_BONDS = 2
                                    ONLY_ANION_CATION_BONDS_AND_NO_ELEMENT_TO_SAME_ELEMENT_BONDS = 3
                                    ONLY_ELEMENT_TO_OXYGEN_BONDS = 4
                                    DO_NOT_CONSIDER_ANION_CATION_BONDS=5
                                    ONLY_CATION_CATION_BONDS=6
            only_bonds_to: (list of str) will only consider bonds to certain elements (e.g. ["O"] for oxygen)
            perc_strength_ICOHP: if no limits are given, this will decide which icohps will still be considered (
            relative to
            the strongest ICOHP)
            valences_from_charges: if True and path to CHARGE.lobster is provided, will use Lobster charges (
            Mulliken) instead of valences
            filename_CHARGE: (str) Path to Charge.lobster
        """

        self.ICOHP = Icohplist(are_coops=are_coops, filename=filename_ICOHP)
        self.Icohpcollection = self.ICOHP.icohpcollection
        self.structure = structure
        self.limits = limits
        self.only_bonds_to = only_bonds_to
        self.are_coops = are_coops
        if are_coops:
            raise ValueError("Algorithm only works correctly for ICOHPLIST.lobster")

        # will check if the additional condition is correctly delivered
        if additional_condition in range(0, 7):
            self.additional_condition = additional_condition
        else:
            raise ValueError("No correct additional condition")

        # will read in valences, will prefer manual setting of valences
        if valences is None:
            if valences_from_charges and filename_CHARGE is not None:
                chg = Charge(filename=filename_CHARGE)
                self.valences = chg.Mulliken
            else:
                bv_analyzer = BVAnalyzer()
                try:
                    self.valences = bv_analyzer.get_valences(structure=self.structure)
                except ValueError:
                    self.valences = None
                    if additional_condition in [1, 3, 5, 6]:
                        print("Valences cannot be assigned, additional_conditions 1 and 3 and 5 and 6 will not work")
        else:
            self.valences = valences

        if limits is None:
            self.lowerlimit = None
            self.upperlimit = None

        else:
            self.lowerlimit = limits[0]
            self.upperlimit = limits[1]

        # will evaluate coordination environments
        self._evaluate_ce(
            lowerlimit=self.lowerlimit,
            upperlimit=self.upperlimit,
            only_bonds_to=only_bonds_to,
            additional_condition=self.additional_condition,
            perc_strength_ICOHP=perc_strength_ICOHP,
        )