Beispiel #1
0
    def std_rel_energies(self) -> Tuple["StandardEnergies", "RelativeEnergies"]:
        std, rel = StandardEnergies(), RelativeEnergies()
        abs_energies_per_atom = {k.reduced_formula: v.energy / k.num_atoms
                                 for k, v in self.items()}
        std_energies_list = []
        for vertex_element in self.elements:
            # This target is needed as some reduced formulas shows molecule
            # ones such as H2 and O2.
            reduced_formula = Composition({vertex_element: 1.0}).reduced_formula
            candidates = filter(lambda x: x[0] == reduced_formula,
                                abs_energies_per_atom.items())
            try:
                min_abs_energy = min([abs_energy_per_atom[1]
                                      for abs_energy_per_atom in candidates])
            except ValueError:
                print(f"Element {vertex_element} does not exist in "
                      f"CompositionEnergies.")
                raise NoElementEnergyError
            std[vertex_element] = min_abs_energy
            std_energies_list.append(min_abs_energy)

        for formula, abs_energy_per_atom in abs_energies_per_atom.items():
            if Composition(formula).is_element:
                continue
            frac = atomic_fractions(formula, self.elements)
            offset = sum([a * b for a, b in zip(frac, std_energies_list)])
            rel[formula] = abs_energy_per_atom - offset

        return std, rel
Beispiel #2
0
    def test_fit(self):
        """
        Take two known matched structures
            1) Ensure match
            2) Ensure match after translation and rotations
            3) Ensure no-match after large site translation
            4) Ensure match after site shuffling
            """
        sm = StructureMatcher()

        self.assertTrue(sm.fit(self.struct_list[0], self.struct_list[1]))

        # Test rotational/translational invariance
        op = SymmOp.from_axis_angle_and_translation([0, 0, 1], 30, False,
                                                    np.array([0.4, 0.7, 0.9]))
        self.struct_list[1].apply_operation(op)
        self.assertTrue(sm.fit(self.struct_list[0], self.struct_list[1]))

        #Test failure under large atomic translation
        self.struct_list[1].translate_sites([0], [.4, .4, .2],
                                            frac_coords=True)
        self.assertFalse(sm.fit(self.struct_list[0], self.struct_list[1]))

        self.struct_list[1].translate_sites([0], [-.4, -.4, -.2],
                                            frac_coords=True)
        # random.shuffle(editor._sites)
        self.assertTrue(sm.fit(self.struct_list[0], self.struct_list[1]))
        #Test FrameworkComporator
        sm2 = StructureMatcher(comparator=FrameworkComparator())
        lfp = read_structure(os.path.join(test_dir, "LiFePO4.cif"))
        nfp = read_structure(os.path.join(test_dir, "NaFePO4.cif"))
        self.assertTrue(sm2.fit(lfp, nfp))
        self.assertFalse(sm.fit(lfp, nfp))

        #Test anonymous fit.
        self.assertEqual(sm.fit_anonymous(lfp, nfp),
                         {Composition("Li"): Composition("Na")})
        self.assertAlmostEqual(sm.get_minimax_rms_anonymous(lfp, nfp)[0],
                               0.096084154118549828)

        #Test partial occupancies.
        s1 = Structure([[3, 0, 0], [0, 3, 0], [0, 0, 3]],
                       [{"Fe": 0.5}, {"Fe": 0.5}, {"Fe": 0.5}, {"Fe": 0.5}],
                       [[0, 0, 0], [0.25, 0.25, 0.25],
                        [0.5, 0.5, 0.5], [0.75, 0.75, 0.75]])
        s2 = Structure([[3, 0, 0], [0, 3, 0], [0, 0, 3]],
                       [{"Fe": 0.25}, {"Fe": 0.5}, {"Fe": 0.5}, {"Fe": 0.75}],
                       [[0, 0, 0], [0.25, 0.25, 0.25],
                        [0.5, 0.5, 0.5], [0.75, 0.75, 0.75]])
        self.assertFalse(sm.fit(s1, s2))
        self.assertFalse(sm.fit(s2, s1))
        s2 = Structure([[3, 0, 0], [0, 3, 0], [0, 0, 3]],
                       [{"Fe": 0.25}, {"Fe": 0.25}, {"Fe": 0.25},
                        {"Fe": 0.25}],
                       [[0, 0, 0], [0.25, 0.25, 0.25],
                        [0.5, 0.5, 0.5], [0.75, 0.75, 0.75]])
        self.assertEqual(sm.fit_anonymous(s1, s2),
                         {Composition("Fe0.5"): Composition("Fe0.25")})

        self.assertAlmostEqual(sm.get_minimax_rms_anonymous(s1, s2)[0], 0)
Beispiel #3
0
    def test_electronegativity(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5)

        s1 = read_structure(os.path.join(test_dir, "Na2Fe2PAsO4S4.cif"))
        s2 = read_structure(os.path.join(test_dir, "Na2Fe2PNO4Se4.cif"))
        self.assertAlmostEqual(sm.fit_with_electronegativity(s1, s2),
                               {Composition('S'): Composition('Se'), Composition('As'): Composition('N')})
Beispiel #4
0
    def test_composition_to_oxidcomposition(self):
        df = DataFrame(data={"composition": [Composition("Fe2O3")]})
        cto = CompositionToOxidComposition()
        df = cto.featurize_dataframe(df, 'composition')
        self.assertEqual(df["composition_oxid"].tolist()[0],
                         Composition({
                             "Fe3+": 2,
                             "O2-": 3
                         }))

        # test error handling
        df = DataFrame(data={"composition": [Composition("Fe2O3")]})
        cto = CompositionToOxidComposition(return_original_on_error=False,
                                           max_sites=2)
        self.assertRaises(ValueError, cto.featurize_dataframe, df,
                          'composition')

        # check non oxi state structure returned correctly
        cto = CompositionToOxidComposition(return_original_on_error=True,
                                           max_sites=2)
        df = cto.featurize_dataframe(df, 'composition')
        self.assertEqual(df["composition_oxid"].tolist()[0],
                         Composition({
                             "Fe": 2,
                             "O": 3
                         }))
Beispiel #5
0
def make_composition_energies_from_mp(
    elements: List[str],
    atom_energy_yaml: Optional[str] = None,
) -> CompositionEnergies:
    """Obtain the energies from Materials Project.

    When the atom_energy_yaml is provided, the total energies are aligned
    via atom energies.
    """
    properties = ["task_id", "full_formula", "final_energy"]
    query = MpQuery(elements, properties=properties)
    comp_es = {}
    if atom_energy_yaml:
        energies = loadfn(atom_energy_yaml)
        diff = {e: energies[e] - mp_energies[e] for e in elements}
    else:
        diff = {e: 0.0 for e in elements}

    for m in query.materials:
        key = Composition(m["full_formula"])
        energy = m["final_energy"]
        for k, v in key.as_dict().items():
            energy += diff[k] * v
        comp_es[key] = CompositionEnergy(energy, m["task_id"])
    print(comp_es)
    comp_es = remove_higher_energy_comp(comp_es)
    print(comp_es)
    return CompositionEnergies(comp_es)
Beispiel #6
0
    def __getitem__(self, idx: int):
        """Get an entry out of the Dataset

        Args:
            idx (int): index of entry in Dataset

        Returns:
            tuple: containing
            - tuple[Tensor, Tensor, LongTensor, LongTensor]: Roost model inputs
            - list[Tensor | LongTensor]: regression or classification targets
            - list[str | int]: identifiers like material_id, composition
        """
        df_idx = self.df.iloc[idx]
        composition = df_idx[self.inputs]
        cry_ids = df_idx[self.identifiers].to_list()

        comp_dict = Composition(composition).get_el_amt_dict()
        elements = list(comp_dict.keys())

        weights = list(comp_dict.values())
        weights = np.atleast_2d(weights).T / np.sum(weights)

        try:
            elem_fea = np.vstack(
                [self.elem_features[element] for element in elements])
        except AssertionError:
            raise AssertionError(
                f"cry-id {cry_ids[0]} [{composition}] contains element types not in embedding"
            )
        except ValueError:
            raise ValueError(
                f"cry-id {cry_ids[0]} [{composition}] composition cannot be parsed into elements"
            )

        nele = len(elements)
        self_idx = []
        nbr_idx = []
        for i, _ in enumerate(elements):
            self_idx += [i] * nele
            nbr_idx += list(range(nele))

        # convert all data to tensors
        elem_weights = Tensor(weights)
        elem_fea = Tensor(elem_fea)
        self_idx = LongTensor(self_idx)
        nbr_idx = LongTensor(nbr_idx)

        targets = []
        for target in self.task_dict:
            if self.task_dict[target] == "regression":
                targets.append(Tensor([df_idx[target]]))
            elif self.task_dict[target] == "classification":
                targets.append(LongTensor([df_idx[target]]))

        return (
            (elem_weights, elem_fea, self_idx, nbr_idx),
            targets,
            *cry_ids,
        )
def mp_query_mock(mocker):
    mock = mocker.patch(
        "pydefect.cli.vasp.make_composition_energies_from_mp.MpEntries")
    mock.return_value.materials = \
        [ComputedEntry(Composition("O8"), -39.58364375, entry_id="mp-1"),
         ComputedEntry(Composition("Mg3"), -4.79068775, entry_id="mp-2"),
         ComputedEntry(Composition("Mg1O1"), -11.96742144, entry_id="mp-3")]
    return mock
Beispiel #8
0
def comp_energies_corr():
    return CompositionEnergies({
        Composition('O8'):
        CompositionEnergy(-39.58364375 + diff["O"] * 8, "mp-1"),
        Composition('Mg3'):
        CompositionEnergy(-4.79068775 + diff["Mg"] * 3, "mp-2"),
        Composition('Mg1O1'):
        CompositionEnergy(-11.96742144 + diff["Mg"] + diff["O"], "mp-3")
    })
 def side_effect_structure(key):
     mock_structure = mocker.Mock()
     if key == Path("Mg") / defaults.contcar:
         mock_structure.composition = Composition("Mg2")
     elif key == Path("O") / defaults.contcar:
         mock_structure.composition = Composition("O2")
     else:
         raise ValueError
     return mock_structure
Beispiel #10
0
def comp_energies():
    return CompositionEnergies({
        Composition('O8'):
        CompositionEnergy(-39.58364375, "mp-1"),
        Composition('Mg3'):
        CompositionEnergy(-4.79068775, "mp-2"),
        Composition('Mg1O1'):
        CompositionEnergy(-11.96742144, "mp-3")
    })
Beispiel #11
0
def formula_to_criteria(formula: str) -> Dict:
    """
    Santizes formula into a dictionary to search with wild cards

    Arguments:
        formula: a chemical formula with wildcards in it for unknown elements

    Returns:
        Mongo style search criteria for this formula
    """
    dummies = "ADEGJLMQRXZ"

    if "*" in formula:
        # Wild card in formula
        nstars = formula.count("*")

        formula_dummies = formula.replace("*", "{}").format(*dummies[:nstars])

        integer_formula = Composition(
            formula_dummies).get_integer_formula_and_factor()[0]
        comp = Composition(integer_formula).reduced_composition
        crit = dict()
        crit["formula_anonymous"] = comp.anonymized_formula
        real_elts = [
            str(e) for e in comp.elements
            if not e.as_dict().get("element", "A") in dummies
        ]

        for el, n in comp.to_reduced_dict.items():
            if el in real_elts:
                crit[f"composition_reduced.{el}"] = n

        return crit

    elif "-" in formula:
        crit = {}
        eles = formula.split("-")
        chemsys = "-".join(sorted(eles))

        crit["chemsys"] = chemsys

        return crit

    elif any(isinstance(el, DummySpecies) for el in Composition(formula)):
        # Assume fully anonymized formula
        return {"formula_anonymous": Composition(formula).anonymized_formula}

    else:
        comp = Composition(formula)
        # Paranoia below about floating-point "equality"
        crit = {}
        crit["nelements"] = len(comp)
        for el, n in comp.to_reduced_dict.items():
            crit[f"composition_reduced.{el}"] = n

        return crit
Beispiel #12
0
    def test_composition_to_structurefromMP(self):
        df = DataFrame(data={"composition": [Composition("Fe2O3"),
                                             Composition("N9Al34Fe234")]})

        cto = CompositionToStructureFromMP()
        df = cto.featurize_dataframe(df, 'composition')
        structures = df["structure"].tolist()
        self.assertTrue(isinstance(structures[0], Structure))
        self.assertGreaterEqual(len(structures[0]), 5)  # has at least 5 sites
        self.assertTrue(math.isnan(structures[1]))
 def setUp(self):
     self.df = pd.DataFrame({
         "composition": [
             Composition("Fe2O3"),
             Composition({
                 Specie("Fe", 2): 1,
                 Specie("O", -2): 1
             })
         ]
     })
Beispiel #14
0
 def test_get_sc_structures(self):
     dist_ref = self.m_hop.length
     start, end, b_sc = self.m_hop.get_sc_structures(vac_mode=False)
     start_site = next(
         filter(lambda x: x.species_string == "Li", start.sites))
     end_site = next(filter(lambda x: x.species_string == "Li", end.sites))
     assert start.composition == end.composition == Composition(
         "Li1 Fe24 P24 O96")
     assert b_sc.composition == Composition("Fe24 P24 O96")
     self.assertAlmostEqual(start_site.distance(end_site), dist_ref, 3)
Beispiel #15
0
def remove_higher_energy_comp(comp_energies: Dict[Composition,
                                                  CompositionEnergy]):
    _l = [[k, v] for k, v in comp_energies.items()]
    result = {}
    for _, grouped_k_v in groupby(
            _l, key=lambda x: Composition(x[0]).reduced_formula):
        formula, comp_e = min(list(grouped_k_v),
                              key=lambda y:
                              (y[1].energy / Composition(y[0]).num_atoms))
        result[formula] = comp_e
    return result
def test_remove_higher_energy_comp():
    comp_es = CompositionEnergies(
        {Composition('Mg1'): CompositionEnergy(-1.9, "mp-2"),
         Composition('Mg2'): CompositionEnergy(-4.0, "mp-3"),
         Composition('O2'): CompositionEnergy(-4.0, "mp-4")})
    actual = remove_higher_energy_comp(comp_es)
    expected = CompositionEnergies(
        {Composition('Mg2'): CompositionEnergy(-4.0, "mp-3"),
         Composition('O2'): CompositionEnergy(-4.0, "mp-4"),})

    assert actual == expected
    def test_str_to_composition(self):
        d = {'comp_str': ["Fe2", "MnO2"]}

        df = DataFrame(data=d)
        df["composition"] = str_to_composition(df["comp_str"])
        self.assertEqual(df["composition"].tolist(), [Composition("Fe2"),
                                                      Composition("MnO2")])

        df["composition_red"] = str_to_composition(df["comp_str"], reduce=True)
        self.assertEqual(df["composition_red"].tolist(), [Composition("Fe"),
                                                           Composition("MnO2")])
Beispiel #18
0
 def side_effect(key):
     mock_vasprun = mocker.Mock()
     if key == Path("Mg") / defaults.vasprun:
         mock_vasprun.final_structure.composition = Composition("Mg2")
         mock_vasprun.final_energy = -10
     elif key == Path("O") / defaults.vasprun:
         mock_vasprun.final_structure.composition = Composition("O2")
         mock_vasprun.final_energy = -20
     else:
         raise ValueError
     return mock_vasprun
    def test_is_ionic(self):
        """Test checking whether a compound is ionic"""

        self.assertTrue(
            is_ionic(Composition({
                Specie("Fe", 2): 1,
                Specie("O", -2): 1
            })))
        self.assertFalse(
            is_ionic(Composition({
                Specie("Fe", 0): 1,
                Specie("Al", 0): 1
            })))
    def test_stoich(self):
        featurizer = Stoichiometry(num_atoms=True)
        df_stoich = Stoichiometry(num_atoms=True).featurize_dataframe(
            self.df, col_id="composition")
        self.assertAlmostEqual(df_stoich["num atoms"][0], 5)
        self.assertAlmostEqual(df_stoich["0-norm"][0], 2)
        self.assertAlmostEqual(df_stoich["7-norm"][0], 0.604895199)

        # Test whether the number of formula units affects result
        original_value = featurizer.featurize(Composition("FeO"))
        self.assertArrayAlmostEqual(
            featurizer.featurize(Composition("Fe0.5O0.5")), original_value)
        self.assertArrayAlmostEqual(featurizer.featurize(Composition("Fe2O2")),
                                    original_value)
    def test_structure_to_composition(self):
        coords = [[0, 0, 0], [0.75, 0.5, 0.75]]
        lattice = Lattice([[3.8401979337, 0.00, 0.00],
                           [1.9200989668, 3.3257101909, 0.00],
                           [0.00, -2.2171384943, 3.1355090603]])
        struct = Structure(lattice, ["Si"] * 2, coords)
        df = DataFrame(data={'structure': [struct]})

        df["composition"] = structure_to_composition(df["structure"])
        self.assertEqual(df["composition"].tolist()[0], Composition("Si2"))

        df["composition_red"] = structure_to_composition(df["structure"],
                                                         reduce=True)
        self.assertEqual(df["composition_red"].tolist()[0], Composition("Si"))
Beispiel #22
0
    def test_str_to_composition(self):
        d = {'comp_str': ["Fe2", "MnO2"]}

        df = DataFrame(data=d)
        df = StrToComposition().featurize_dataframe(df, 'comp_str')

        self.assertEqual(df["composition"].tolist(),
                         [Composition("Fe2"), Composition("MnO2")])

        stc = StrToComposition(reduce=True, target_col_id='composition_red')
        df = stc.featurize_dataframe(df, 'comp_str')

        self.assertEqual(df["composition_red"].tolist(),
                         [Composition("Fe"), Composition("MnO2")])
    def test_miedema_all(self):
        df = pd.DataFrame({
            "composition": [
                Composition("TiZr"),
                Composition("Mg10Cu50Ca40"),
                Composition("Fe2O3")
            ]
        })
        miedema = Miedema(struct_types='all')
        self.assertTrue(miedema.precheck(df["composition"].iloc[0]))
        self.assertFalse(miedema.precheck(df["composition"].iloc[-1]))
        self.assertAlmostEqual(miedema.precheck_dataframe(df, "composition"),
                               2 / 3)

        # test precheck for oxidation-state decorated compositions
        df = CompositionToOxidComposition(return_original_on_error=True).\
            featurize_dataframe(df, 'composition')
        self.assertTrue(miedema.precheck(df["composition_oxid"].iloc[0]))
        self.assertFalse(miedema.precheck(df["composition_oxid"].iloc[-1]))
        self.assertAlmostEqual(
            miedema.precheck_dataframe(df, "composition_oxid"), 2 / 3)

        mfps = miedema.featurize_dataframe(df, col_id="composition")
        self.assertAlmostEqual(mfps['Miedema_deltaH_inter'][0],
                               -0.003445022152)
        self.assertAlmostEqual(mfps['Miedema_deltaH_amor'][0], 0.0707658836300)
        self.assertAlmostEqual(mfps['Miedema_deltaH_ss_min'][0], 0.03663599755)

        self.assertAlmostEqual(mfps['Miedema_deltaH_inter'][1],
                               -0.235125978427)
        self.assertAlmostEqual(mfps['Miedema_deltaH_amor'][1], -0.164541848271)
        self.assertAlmostEqual(mfps['Miedema_deltaH_ss_min'][1],
                               -0.05280843311)

        self.assertAlmostEqual(math.isnan(mfps['Miedema_deltaH_inter'][2]),
                               True)
        self.assertAlmostEqual(math.isnan(mfps['Miedema_deltaH_amor'][2]),
                               True)
        self.assertAlmostEqual(math.isnan(mfps['Miedema_deltaH_ss_min'][2]),
                               True)

        # make sure featurization works equally for compositions with or without
        # oxidation states
        mfps = miedema.featurize_dataframe(df, col_id="composition_oxid")
        self.assertAlmostEqual(mfps['Miedema_deltaH_inter'][0],
                               -0.003445022152)
        self.assertAlmostEqual(mfps['Miedema_deltaH_amor'][0], 0.0707658836300)
        self.assertAlmostEqual(mfps['Miedema_deltaH_ss_min'][0], 0.03663599755)
Beispiel #24
0
    def update_sites(self, directory, ignore_magmom=False):
        """
        Based on the CONTCAR and OUTCAR of a geometry optimization, update the
        site coordinates and magnetic moments that were optimized. Note that
        this method relies on the cation configuration of the cathode not
        having changed.

        Args:
            directory (str): Directory in which the geometry optimization
                output files (i.e. CONTCAR and OUTCAR) are stored.
            ignore_magmom (bool): Flag that indicates that the final magnetic
                moments of the optimized structure should be ignored. This means
                that the magnetic moments of the Cathode structure will
                remain the same.

        Returns:
            None

        """

        new_cathode = Cathode.from_file(os.path.join(directory, "CONTCAR"))

        out = Outcar(os.path.join(directory, "OUTCAR"))

        if ignore_magmom:
            magmom = [site.properties["magmom"] for site in self.sites
                      if site.species != Composition()]
        else:
            magmom = [site["tot"] for site in out.magnetization]

        if len(out.magnetization) != 0:
            new_cathode.add_site_property("magmom", magmom)

        # Update the lattice
        self.lattice = new_cathode.lattice

        # Update the coordinates of the occupied sites.
        new_index = 0
        for i, site in enumerate(self):

            # If the site is not empty
            if site.species != Composition():
                new_site = new_cathode.sites[new_index]
                # Update the site coordinates
                self.replace(i, species=new_site.species,
                             coords=new_site.frac_coords,
                             properties=new_site.properties)
                new_index += 1
def get_insertion_energy(
    base_entry: ComputedStructureEntry,
    inserted_entry: ComputedStructureEntry,
    migrating_ion_entry: ComputedEntry,
) -> float:
    """
    Calculate the insertion energy for a given inserted entry
    Args:
        base_entry: The entry for the host structure
        inserted_entry: The entry for the inserted structure
        migrating_ion_entry: The entry for the metallic phase of the working ion
    Returns:
        The insertion energy defined as (E[inserted] - (E[Base] + n * E[working_ion]))/(n)
        Where n is the number of working ions and E[inserted].
        Additionally, and E[base] and E[inserted] are for structures of the same size (sans working ion)
    """
    wi_ = str(migrating_ion_entry.composition.elements[0])
    comp_inserted_no_wi = inserted_entry.composition.as_dict()
    comp_inserted_no_wi.pop(wi_)
    comp_inserted_no_wi = Composition.from_dict(comp_inserted_no_wi)
    _, factor_inserted = comp_inserted_no_wi.get_reduced_composition_and_factor(
    )
    _, factor_base = base_entry.composition.get_reduced_composition_and_factor(
    )
    e_base = base_entry.energy * factor_inserted / factor_base
    e_insert = inserted_entry.energy
    e_wi = migrating_ion_entry.energy_per_atom
    n_wi = inserted_entry.composition[wi_]

    return (e_insert - (e_base + n_wi * e_wi)) / n_wi
Beispiel #26
0
def prepare_entry(structure_type, tot_e, species):
    """
    Prepare entries from total energy and species.

    Args:
        structure_type(str): "garnet" or "perovskite"
        tot_e (float): total energy in eV/f.u.
        species (dict): species in dictionary.

    Returns:
        ce (ComputedEntry)
    """

    formula = spe2form(structure_type, species)
    composition = Composition(formula)
    elements = [el.name for el in composition]

    potcars = ["pbe %s" % CONFIG['POTCAR'][el] for el in elements]

    parameters = {"potcar_symbols": list(potcars), "oxide_type": 'oxide'}

    for el in elements:
        if el in LDAUU:
            parameters.update({"hubbards": {el: LDAUU[el]}})

    ce = ComputedEntry(composition=composition,
                       energy=0,
                       parameters=parameters)
    ce.uncorrected_energy = tot_e
    compat = MaterialsProjectCompatibility()
    ce = compat.process_entry(ce)  # Correction added

    return ce
Beispiel #27
0
    def run(self):
        logger.info("Starting FileMaterials Builder.")
        with open(self._data_file, 'rt') as f:
            line_no = 0
            lines = [line for line in f]  # only good for smaller files
            pbar = tqdm(lines)
            for line in pbar:
                line = line.strip()
                if line and not line.startswith("#"):
                    line_no += 1
                    if line_no > self.header_lines:
                        line = line.split(self._delimiter)
                        if "-" in line[0]:
                            search_val = line[0]
                            search_key = "material_id"
                        else:
                            search_key = "formula_reduced_abc"
                            search_val = Composition(line[0]).\
                                reduced_composition.alphabetical_formula

                        key = line[1]
                        val = line[2]
                        try:
                            val = float(val)
                        except:
                            pass

                        self._materials.update({search_key: search_val}, {"$set": {key: val}})

        logger.info("FileMaterials Builder finished processing")
Beispiel #28
0
def FullChemicalPotentialWindow(target_phase, key_element):
    chemsys = key_element + '-' + Composition(target_phase).chemical_system
    with MPRester(api_key='') as mpr:
        entries = mpr.get_entries_in_chemsys(chemsys)

    pd_closed = PhaseDiagram(entries)
    transition_chempots = pd_closed.get_transition_chempots(
        Element(key_element))
    # The exact mu value used to construct the plot for each range is
    # the average of the endpoints of the range, with the exception of the last range,
    # which is plotted at the value of the last endpoint minus 0.1.
    # https://matsci.org/t/question-on-phase-diagram-app-chemical-potential/511
    average_chempots = []
    if len(transition_chempots) > 1:
        for i in range(len(transition_chempots) - 1):
            ave = (transition_chempots[i] + transition_chempots[i + 1]) / 2
            average_chempots.append(ave)
        average_chempots.append(transition_chempots[-1] - 0.1)
    elif len(transition_chempots) == 1:
        # prepare for binary systems, of which two endnodes tielined directly, like Li-Zr
        average_chempots.append(transition_chempots[0])
    average_chempots = np.round(average_chempots, 3)

    boolean_list = []
    for chempot in average_chempots:
        # GrandPotentialPhaseDiagram works good even for binary systems to find stable phases
        pd_open = GrandPotentialPhaseDiagram(entries,
                                             {Element(key_element): chempot})
        stable_phases = [entry.name for entry in pd_open.stable_entries]
        boolean_list.append(target_phase in stable_phases)
    return (False not in boolean_list)
Beispiel #29
0
    def test_structure_to_composition(self):
        coords = [[0, 0, 0], [0.75, 0.5, 0.75]]
        lattice = Lattice([[3.8401979337, 0.00, 0.00],
                           [1.9200989668, 3.3257101909, 0.00],
                           [0.00, -2.2171384943, 3.1355090603]])
        struct = Structure(lattice, ["Si"] * 2, coords)
        df = DataFrame(data={'structure': [struct]})

        stc = StructureToComposition()
        df = stc.featurize_dataframe(df, 'structure')
        self.assertEqual(df["composition"].tolist()[0], Composition("Si2"))

        stc = StructureToComposition(reduce=True,
                                     target_col_id='composition_red')
        df = stc.featurize_dataframe(df, 'structure')
        self.assertEqual(df["composition_red"].tolist()[0], Composition("Si"))
 def test_band_center(self):
     df_band_center = BandCenter().featurize_dataframe(self.df,
                                                       col_id="composition")
     self.assertAlmostEqual(df_band_center["band center"][0], -2.672486385)
     self.assertAlmostEqual(
         BandCenter().featurize(Composition('Ag33O500V200'))[0],
         -2.7337150991)
def get_comp_data(un_data):
    element_universe = [str(e) for e in Element]
    dict_element = {}
    for i, j in enumerate(element_universe):
        dict_element[str(j)] = i
    stoich_array = np.zeros((len(un_data), 3), dtype=float)
    at_num_array = np.zeros((len(un_data), 3), dtype=int)
    electroneg_array = np.zeros((len(un_data), 3), dtype=float)
    comp_array=[]
    for index, entry in enumerate(un_data):
        comp = Composition(entry[2])
        comp_array.append(comp.formula)
        temp_dict = dict(comp.get_el_amt_dict())
        for count, key in enumerate(temp_dict.keys()):
            stoich_array[index][count] = temp_dict[key]
            if key not in ['D', 'T']:
                at_num_array[index][count] = Element(key).Z
                electroneg_array[index][count] = Element(key).X
            else:
                at_num_array[index][count] = Element('H').Z
                electroneg_array[index][count] = Element('H').X
    return (comp_array,stoich_array,at_num_array,electroneg_array)
Beispiel #32
0
    def __init__(self, entries, comp_dict=None):
        """
        Args:
            entries:
                Entries list containing both Solids and Ions
            comp_dict:
                Dictionary of compositions
        """
        self._solid_entries = list()
        self._ion_entries = list()
        for entry in entries:
            if entry.phase_type == "Solid":
                self._solid_entries.append(entry)
            elif entry.phase_type == "Ion":
                self._ion_entries.append(entry)
            else:
                raise StandardError("Incorrect Phase type - needs to be \
                Pourbaix entry of phase type Ion/Solid")
        self._unprocessed_entries = self._solid_entries + self._ion_entries
        self._elt_comp = comp_dict
        if comp_dict:
            self._multielement = True
            self.pourbaix_elements = [key for key in comp_dict]
            w = [comp_dict[key] for key in comp_dict]
            A = []
            for comp in comp_dict:
                m = re.search(r"\[([^\[\]]+)\]|\(aq\)", comp)
                if m:
                    comp_obj = Ion.from_formula(comp)
                else:
                    comp_obj = Composition.from_formula(comp)
                Ai = []
                for elt in self.pourbaix_elements:
                    Ai.append(comp_obj[Element(elt)])
                A.append(Ai)
            A = np.array(A).T.astype(float)
            w = np.array(w)
            A /= np.dot([A[i].sum() for i in xrange(len(A))], w)
            x = np.linalg.solve(A, w)
            self._elt_comp = dict(zip(self.pourbaix_elements, x))

        else:
            self._multielement = False
            self.pourbaix_elements = [el.symbol
                                      for el in entries[0].composition.elements
                                      if el.symbol not in ["H", "O"]]
        self._make_pourbaixdiagram()
    factors = {'Co': 1.7/3.2/0.6, 'Fe': 2.1/3.9/0.6}
    for fldidx,fields_str in enumerate(fields_strings):
        fields = fields_str.split(' -> ')
        for elidx,elem in enumerate(chemsys[:-1]):
            print fields_str, elem
            plt = plotter.get_plot()
            title = elem+': '+fields_str
            if fldidx == 3 and elidx == 1: title = fields_str
            plt.suptitle(title, fontsize=24)
            plt.triplot(grid_triang, 'k:')

            # heatmap
            x, y, z = [], [], []
            for idx,(comp,cid) in enumerate(comps_cids):
                comp_str = comp if args.dev else doc[cid]['_id']
                composition = Composition(comp_str)
                x0, x1, x2 = [composition.get_atomic_fraction(el) for el in chemsys]
                x.append(x0+x2/2.) # NOTE x0 might need to be replace with x1
                y.append(x2*math.sqrt(3.)/2.)
                if fldidx < 3:
                    zval = mpfile.document[comp_str]['{} XMCD'.format(elem)][fields[0]][fields[1]]
                    if fldidx == 0: norms[elem] = zval
                    elif fldidx == 1: xmcd_diffs[elem] = zval
                    else: xmcd_diffs[elem] -= zval
                    z.append(zval)
                else:
                    mag += xmcd_diffs[elem] * factors[elem] * norms[elem]
                    if elidx == 1: z.append(mag)

            if fldidx == 3 and elidx == 0: continue
            #x0, x1, x2 = 1/2., 1/3., 1/6.