示例#1
0
    def setUp(self):
        self.comp = list()
        self.comp.append(Composition.from_formula("Li3Fe2(PO4)3"))
        self.comp.append(Composition.from_formula("Li3Fe(PO4)O"))
        self.comp.append(Composition.from_formula("LiMn2O4"))
        self.comp.append(Composition.from_formula("Li4O4"))
        self.comp.append(Composition.from_formula("Li3Fe2Mo3O12"))
        self.comp.append(Composition.from_formula("Li3Fe2((PO4)3(CO3)5)2"))
        self.comp.append(Composition.from_formula("Li1.5Si0.5"))
        self.comp.append(Composition.from_formula("ZnOH"))

        self.indeterminate_comp = []
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula(
                "Co1", True))
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula(
                "Co1", False))
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula(
                "co2o3"))
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula(
                "ncalu"))
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula(
                "calun"))
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula(
                "liCoo2n (pO4)2"))
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula(
                "(co)2 (PO)4"))
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula("Fee3"))
示例#2
0
 def test_sub(self):
     self.assertEqual((self.comp[0]
                       - Composition.from_formula("Li2O")).formula,
                      "Li1 Fe2 P3 O11",
                      "Incorrect composition after addition!")
     self.assertEqual((self.comp[0] - {"Fe": 2, "O": 3}).formula,
                      "Li3 P3 O9")
示例#3
0
 def test_sub(self):
     self.assertEqual(
         (self.comp[0] - Composition.from_formula("Li2O")).formula,
         "Li1 Fe2 P3 O11", "Incorrect composition after addition!")
     self.assertEqual((self.comp[0] - {
         "Fe": 2,
         "O": 3
     }).formula, "Li3 P3 O9")
示例#4
0
 def test_reduced_composition(self):
     correct_reduced_formulas = [
         'Li3Fe2(PO4)3', 'Li3FePO5', 'LiMn2O4', 'Li2O2', 'Li3Fe2(MoO4)3',
         'Li3Fe2P6(C5O27)2', 'Li1.5Si0.5', 'ZnHO'
     ]
     for i in xrange(len(self.comp)):
         self.assertEqual(
             self.comp[i].get_reduced_composition_and_factor()[0],
             Composition.from_formula(correct_reduced_formulas[i]))
示例#5
0
 def test_getmu_vertices_stability_phase(self):
     results = self.analyzer.getmu_vertices_stability_phase(Composition.from_formula("LiFeO2"), Element("O"))
     self.assertAlmostEqual(len(results), 6)
     test_equality = False
     for c in results:
         if abs(c[Element("O")]+7.115) < 1e-2 and abs(c[Element("Fe")]+6.596) < 1e-2 and \
                 abs(c[Element("Li")]+3.931) < 1e-2:
             test_equality = True
     self.assertTrue(test_equality,"there is an expected vertex missing in the list")
示例#6
0
 def test_indeterminate_formula(self):
     correct_formulas = [["Co1"], ["Co1", "C1 O1"], ["Co2 O3", "C1 O5"],
                         ["N1 Ca1 Lu1", "U1 Al1 C1 N1"],
                         ["N1 Ca1 Lu1", "U1 Al1 C1 N1"],
                         ["Li1 Co1 P2 N1 O10", "Li1 P2 C1 N1 O11",
                          "Li1 Co1 Po8 N1 O2", "Li1 Po8 C1 N1 O3"],
                         ["Co2 P4 O4", "Co2 Po4", "P4 C2 O6",
                          "Po4 C2 O2"], []]
     for i, c in enumerate(correct_formulas):
         self.assertEqual([Composition.from_formula(comp) for comp in c],
                          self.indeterminate_comp[i])
示例#7
0
 def test_getmu_vertices_stability_phase(self):
     results = self.analyzer.getmu_vertices_stability_phase(
         Composition.from_formula("LiFeO2"), Element("O"))
     self.assertAlmostEqual(len(results), 6)
     test_equality = False
     for c in results:
         if abs(c[Element("O")]+7.115) < 1e-2 and abs(c[Element("Fe")]+6.596) < 1e-2 and \
                 abs(c[Element("Li")]+3.931) < 1e-2:
             test_equality = True
     self.assertTrue(test_equality,
                     "there is an expected vertex missing in the list")
示例#8
0
 def test_indeterminate_formula(self):
     correct_formulas = [["Co1"], ["Co1", "C1 O1"], ["Co2 O3", "C1 O5"],
                         ["N1 Ca1 Lu1", "U1 Al1 C1 N1"],
                         ["N1 Ca1 Lu1", "U1 Al1 C1 N1"],
                         [
                             "Li1 Co1 P2 N1 O10", "Li1 P2 C1 N1 O11",
                             "Li1 Co1 Po8 N1 O2", "Li1 Po8 C1 N1 O3"
                         ],
                         ["Co2 P4 O4", "Co2 Po4", "P4 C2 O6", "Po4 C2 O2"],
                         []]
     for i, c in enumerate(correct_formulas):
         self.assertEqual([Composition.from_formula(comp) for comp in c],
                          self.indeterminate_comp[i])
示例#9
0
 def __str__(self):
     reactant_str = []
     product_str = []
     for i in range(self._num_comp):
         comp = self._all_comp[i]
         coeff = self._coeffs[i]
         red_comp = Composition.from_formula(comp.reduced_formula)
         scale_factor = comp.num_atoms / red_comp.num_atoms
         scaled_coeff = coeff * scale_factor
         if scaled_coeff < 0:
             reactant_str.append("{:.3f} {}".format(-scaled_coeff, comp.reduced_formula))
         elif scaled_coeff > 0:
             product_str.append("{:.3f} {}".format(scaled_coeff, comp.reduced_formula))
     return " + ".join(reactant_str) + " -> " + " + ".join(product_str)
示例#10
0
 def __str__(self):
     reactant_str = []
     product_str = []
     for i in range(self._num_comp):
         comp = self._all_comp[i]
         coeff = self._coeffs[i]
         red_comp = Composition.from_formula(comp.reduced_formula)
         scale_factor = comp.num_atoms / red_comp.num_atoms
         scaled_coeff = coeff * scale_factor
         if scaled_coeff < 0:
             reactant_str.append("{:.3f} {}".format(-scaled_coeff,
                                                    comp.reduced_formula))
         elif scaled_coeff > 0:
             product_str.append("{:.3f} {}".format(scaled_coeff,
                                                   comp.reduced_formula))
     return " + ".join(reactant_str) + " -> " + " + ".join(product_str)
示例#11
0
    def setUp(self):
        self.comp = list()
        self.comp.append(Composition.from_formula("Li3Fe2(PO4)3"))
        self.comp.append(Composition.from_formula("Li3Fe(PO4)O"))
        self.comp.append(Composition.from_formula("LiMn2O4"))
        self.comp.append(Composition.from_formula("Li4O4"))
        self.comp.append(Composition.from_formula("Li3Fe2Mo3O12"))
        self.comp.append(Composition.from_formula("Li3Fe2((PO4)3(CO3)5)2"))
        self.comp.append(Composition.from_formula("Li1.5Si0.5"))
        self.comp.append(Composition.from_formula("ZnOH"))

        self.indeterminate_comp = []
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula("Co1",
                                                                       True)
        )
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula("Co1",
                                                                       False)
        )
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula("co2o3")
        )
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula("ncalu")
        )
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula("calun")
        )
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula(
                "liCoo2n (pO4)2")
        )
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula(
                "(co)2 (PO)4")
        )
        self.indeterminate_comp.append(
            Composition.ranked_compositions_from_indeterminate_formula("Fee3"))
示例#12
0
 def test_getmu_vertices_stability_phase(self):
     results = self.analyzer.getmu_vertices_stability_phase(Composition.from_formula("LiFeO2"), Element("O"))
     self.assertAlmostEqual(results[5][Element("O")], -7.11535414)
     self.assertAlmostEqual(results[10][Element("Li")], -3.93161519)
     self.assertAlmostEqual(results[0][Element("Fe")], -10.45183356)
示例#13
0
    def from_steps(step1, step2, normalization_els):
        """
        Creates a ConversionVoltagePair from two steps in the element profile
        from a PD analysis.

        Args:
            step1: Starting step
            step2: Ending step
            normalization_els: Elements to normalize the reaction by. To
                ensure correct capacities.
        """
        working_ion_entry = step1["element_reference"]
        working_ion = working_ion_entry.composition.elements[0].symbol
        voltage = -step1["chempot"] + working_ion_entry.energy_per_atom
        mAh = (step2["evolution"] - step1["evolution"]) \
            * Charge(1, "e").to("C") * Time(1, "s").to("h") * AVOGADROS_CONST\
            * 1000
        licomp = Composition.from_formula(working_ion)
        prev_rxn = step1["reaction"]
        reactants = {
            comp: abs(prev_rxn.get_coeff(comp))
            for comp in prev_rxn.products if comp != licomp
        }

        curr_rxn = step2["reaction"]
        products = {
            comp: abs(curr_rxn.get_coeff(comp))
            for comp in curr_rxn.products if comp != licomp
        }

        reactants[licomp] = (step2["evolution"] - step1["evolution"])

        rxn = BalancedReaction(reactants,
                               products,
                               remove_spectator_species=True)

        for el, amt in normalization_els.items():
            if rxn.get_el_amount(el) > 1e-6:
                rxn.normalize_to_element(el, amt)
                break

        prev_mass_dischg = sum([
            prev_rxn.all_comp[i].weight * abs(prev_rxn.coeffs[i])
            for i in xrange(len(prev_rxn.all_comp))
        ]) / 2
        vol_charge = sum([
            abs(prev_rxn.get_coeff(e.composition)) * e.structure.volume
            for e in step1["entries"]
            if e.composition.reduced_formula != working_ion
        ])
        mass_discharge = sum([
            curr_rxn.all_comp[i].weight * abs(curr_rxn.coeffs[i])
            for i in xrange(len(curr_rxn.all_comp))
        ]) / 2
        mass_charge = prev_mass_dischg
        mass_discharge = mass_discharge
        vol_discharge = sum([
            abs(curr_rxn.get_coeff(e.composition)) * e.structure.volume
            for e in step2["entries"]
            if e.composition.reduced_formula != working_ion
        ])

        totalcomp = Composition({})
        for comp in prev_rxn.products:
            if comp.reduced_formula != working_ion:
                totalcomp += comp * abs(prev_rxn.get_coeff(comp))
        frac_charge = totalcomp.get_atomic_fraction(Element(working_ion))

        totalcomp = Composition({})
        for comp in curr_rxn.products:
            if comp.reduced_formula != working_ion:
                totalcomp += comp * abs(curr_rxn.get_coeff(comp))
        frac_discharge = totalcomp.get_atomic_fraction(Element(working_ion))

        rxn = rxn
        entries_charge = step2["entries"]
        entries_discharge = step1["entries"]

        return ConversionVoltagePair(rxn, voltage, mAh, vol_charge,
                                     vol_discharge, mass_charge,
                                     mass_discharge, frac_charge,
                                     frac_discharge, entries_charge,
                                     entries_discharge, working_ion_entry)
示例#14
0
    def from_steps(step1, step2, normalization_els):
        """
        Creates a ConversionVoltagePair from two steps in the element profile
        from a PD analysis.

        Args:
            step1:
                Starting step
            step2:
                Ending step
            normalization_els:
                Elements to normalize the reaction by. To ensure correct
                capacities.
        """
        working_ion_entry = step1["element_reference"]
        working_ion = working_ion_entry.composition.elements[0].symbol
        voltage = -step1["chempot"] + working_ion_entry.energy_per_atom
        mAh = (step2["evolution"] - step1["evolution"]) \
            * Charge(1, "e").to("C") * Time(1, "s").to("h") * AVOGADROS_CONST\
            * 1000
        licomp = Composition.from_formula(working_ion)
        prev_rxn = step1["reaction"]
        reactants = {comp: abs(prev_rxn.get_coeff(comp))
                     for comp in prev_rxn.products if comp != licomp}
        curr_rxn = step2["reaction"]
        products = {comp: abs(curr_rxn.get_coeff(comp))
                    for comp in curr_rxn.products if comp != licomp}
        reactants[licomp] = (step2["evolution"] - step1["evolution"])

        rxn = BalancedReaction(reactants, products)

        for el, amt in normalization_els.items():
            if rxn.get_el_amount(el) != 0:
                rxn.normalize_to_element(el, amt)
                break

        prev_mass_dischg = sum([prev_rxn.all_comp[i].weight
                                * abs(prev_rxn.coeffs[i])
                                for i in xrange(len(prev_rxn.all_comp))]) / 2
        vol_charge = sum([abs(prev_rxn.get_coeff(e.composition))
                          * e.structure.volume
                          for e in step1["entries"]
                          if e.composition.reduced_formula != working_ion])
        mass_discharge = sum([curr_rxn.all_comp[i].weight
                              * abs(curr_rxn.coeffs[i])
                              for i in xrange(len(curr_rxn.all_comp))]) / 2
        mass_charge = prev_mass_dischg
        mass_discharge = mass_discharge
        vol_discharge = sum([abs(curr_rxn.get_coeff(e.composition))
                             * e.structure.volume
                             for e in step2["entries"]
                             if e.composition.reduced_formula != working_ion])

        totalcomp = Composition({})
        for comp in prev_rxn.products:
            if comp.reduced_formula != working_ion:
                totalcomp += comp * abs(prev_rxn.get_coeff(comp))
        frac_charge = totalcomp.get_atomic_fraction(Element(working_ion))

        totalcomp = Composition({})
        for comp in curr_rxn.products:
            if comp.reduced_formula != working_ion:
                totalcomp += comp * abs(curr_rxn.get_coeff(comp))
        frac_discharge = totalcomp.get_atomic_fraction(Element(working_ion))

        rxn = rxn
        entries_charge = step2["entries"]
        entries_discharge = step1["entries"]

        return ConversionVoltagePair(rxn, voltage, mAh, vol_charge,
                                     vol_discharge, mass_charge,
                                     mass_discharge,
                                     frac_charge, frac_discharge,
                                     entries_charge, entries_discharge,
                                     working_ion_entry)
示例#15
0
    def __init__(self, struct):
        """
        Args:
            struct:
                A pymatgen.core.structure.Structure object.
        """
        block = CifFile.CifBlock()
        latt = struct.lattice
        comp = struct.composition
        no_oxi_comp = Composition(comp.formula)
        block["_symmetry_space_group_name_H-M"] = "P 1"
        for cell_attr in ['a', 'b', 'c']:
            block["_cell_length_" + cell_attr] = str(getattr(latt, cell_attr))
        for cell_attr in ['alpha', 'beta', 'gamma']:
            block["_cell_angle_" + cell_attr] = str(getattr(latt, cell_attr))
        block["_chemical_name_systematic"] = "Generated by pymatgen"
        block["_symmetry_Int_Tables_number"] = 1
        block["_chemical_formula_structural"] = str(no_oxi_comp
                                                    .reduced_formula)
        block["_chemical_formula_sum"] = str(no_oxi_comp.formula)
        block["_cell_volume"] = str(latt.volume)

        reduced_comp = Composition.from_formula(no_oxi_comp.reduced_formula)
        el = no_oxi_comp.elements[0]
        amt = comp[el]
        fu = int(amt / reduced_comp[Element(el.symbol)])

        block["_cell_formula_units_Z"] = str(fu)
        block.AddCifItem(([["_symmetry_equiv_pos_site_id",
                            "_symmetry_equiv_pos_as_xyz"]],
                          [[["1"], ["x, y, z"]]]))

        contains_oxidation = True
        try:
            symbol_to_oxinum = {str(el): float(el.oxi_state)
                                for el in comp.elements}
        except AttributeError:
            symbol_to_oxinum = {el.symbol: 0 for el in comp.elements}
            contains_oxidation = False
        if contains_oxidation:
            block.AddCifItem(([["_atom_type_symbol",
                                "_atom_type_oxidation_number"]],
                              [[symbol_to_oxinum.keys(),
                                symbol_to_oxinum.values()]]))

        atom_site_type_symbol = []
        atom_site_symmetry_multiplicity = []
        atom_site_fract_x = []
        atom_site_fract_y = []
        atom_site_fract_z = []
        atom_site_attached_hydrogens = []
        atom_site_B_iso_or_equiv = []
        atom_site_label = []
        atom_site_occupancy = []
        count = 1
        for site in struct:
            for sp, occu in site.species_and_occu.items():
                atom_site_type_symbol.append(str(sp))
                atom_site_symmetry_multiplicity.append("1")
                atom_site_fract_x.append("{0:f}".format(site.a))
                atom_site_fract_y.append("{0:f}".format(site.b))
                atom_site_fract_z.append("{0:f}".format(site.c))
                atom_site_attached_hydrogens.append("0")
                atom_site_B_iso_or_equiv.append(".")
                atom_site_label.append("{}{}".format(sp.symbol, count))
                atom_site_occupancy.append(str(occu))
                count += 1

        block["_atom_site_type_symbol"] = atom_site_type_symbol
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_label": atom_site_label})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_symmetry_multiplicity":
                         atom_site_symmetry_multiplicity})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_fract_x": atom_site_fract_x})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_fract_y": atom_site_fract_y})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_fract_z": atom_site_fract_z})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_attached_hydrogens":
                         atom_site_attached_hydrogens})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_B_iso_or_equiv":
                         atom_site_B_iso_or_equiv})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_occupancy": atom_site_occupancy})

        self._cf = CifFile.CifFile()
        # AJ says: CIF Block names cannot be more than 75 characters or you
        # get an Exception
        self._cf[comp.reduced_formula[0:74]] = block
示例#16
0
    def get_element_profile(self, element, comp, comp_tol=1e-5):
        """
        Provides the element evolution data for a composition.
        For example, can be used to analyze Li conversion voltages by varying
        uLi and looking at the phases formed. Also can be used to analyze O2
        evolution by varying uO2.

        Args:
            element:
                An element. Must be in the phase diagram.
            comp:
                A Composition
            comp_tol:
                The tolerance to use when calculating decompositions. Phases
                with amounts less than this tolerance are excluded. Defaults to
                1e-5.

        Returns:
            Evolution data as a list of dictionaries of the following format:
            [ {'chempot': -10.487582010000001, 'evolution': -2.0,
            'reaction': Reaction Object], ...]
        """
        if element not in self._pd.elements:
            raise ValueError("get_transition_chempots can only be called with"
                             " elements in the phase diagram.")
        chempots = self.get_transition_chempots(element)
        stable_entries = self._pd.stable_entries
        gccomp = Composition({el: amt for el, amt in comp.items()
                              if el != element})
        elref = self._pd.el_refs[element]
        elcomp = Composition.from_formula(element.symbol)
        prev_decomp = []
        evolution = []

        def are_same_decomp(decomp1, decomp2):
            for comp in decomp2:
                if comp not in decomp1:
                    return False
            return True

        for c in chempots:
            gcpd = GrandPotentialPhaseDiagram(
                stable_entries, {element: c - 0.01}, self._pd.elements
            )
            analyzer = PDAnalyzer(gcpd)
            gcdecomp = analyzer.get_decomposition(gccomp)
            decomp = [gcentry.original_entry.composition
                      for gcentry, amt in gcdecomp.items()
                      if amt > comp_tol]
            decomp_entries = [gcentry.original_entry
                              for gcentry, amt in gcdecomp.items()
                              if amt > comp_tol]

            if not are_same_decomp(prev_decomp, decomp):
                if elcomp not in decomp:
                    decomp.insert(0, elcomp)
                rxn = Reaction([comp], decomp)
                rxn.normalize_to(comp)
                prev_decomp = decomp
                amt = -rxn.coeffs[rxn.all_comp.index(elcomp)]
                evolution.append({'chempot': c,
                                  'evolution': amt,
                                  'element_reference': elref,
                                  'reaction': rxn, 'entries': decomp_entries})

        return evolution
示例#17
0
 def test_getmu_range_stability_phase(self):
     results = self.analyzer.getmu_range_stability_phase(Composition.from_formula("LiFeO2"),Element("O"))
     self.assertAlmostEqual(results[Element("O")][1], -4.4501812249999997)
     self.assertAlmostEqual(results[Element("Fe")][0], -6.5961470999999996)
     self.assertAlmostEqual(results[Element("Li")][0], -3.6250022625000007)
示例#18
0
    def __init__(self, struct, find_spacegroup=False):
        block = CifFile.CifBlock()
        latt = struct.lattice
        comp = struct.composition
        no_oxi_comp = Composition(comp.formula)
        spacegroup = ("P 1", 1)
        if find_spacegroup:
            sf = SymmetryFinder(struct, 0.001)
            spacegroup = (sf.get_spacegroup_symbol(),
                          sf.get_spacegroup_number())
        block["_symmetry_space_group_name_H-M"] = spacegroup[0]
        for cell_attr in ['a', 'b', 'c']:
            block["_cell_length_" + cell_attr] = str(getattr(latt, cell_attr))
        for cell_attr in ['alpha', 'beta', 'gamma']:
            block["_cell_angle_" + cell_attr] = float(getattr(latt, cell_attr))
        block["_chemical_name_systematic"] = "Generated by pymatgen"
        block["_symmetry_Int_Tables_number"] = spacegroup[1]
        block["_chemical_formula_structural"] = str(
            no_oxi_comp.reduced_formula)
        block["_chemical_formula_sum"] = str(no_oxi_comp.formula)
        block["_cell_volume"] = str(latt.volume)

        reduced_comp = Composition.from_formula(no_oxi_comp.reduced_formula)
        el = no_oxi_comp.elements[0]
        amt = comp[el]
        fu = int(amt / reduced_comp[Element(el.symbol)])

        block["_cell_formula_units_Z"] = str(fu)
        block.AddCifItem(
            ([["_symmetry_equiv_pos_site_id",
               "_symmetry_equiv_pos_as_xyz"]], [[["1"], ["x, y, z"]]]))

        contains_oxidation = True
        try:
            symbol_to_oxinum = {
                str(el): float(el.oxi_state)
                for el in comp.elements
            }
        except AttributeError:
            symbol_to_oxinum = {el.symbol: 0 for el in comp.elements}
            contains_oxidation = False
        if contains_oxidation:
            block.AddCifItem(
                ([["_atom_type_symbol", "_atom_type_oxidation_number"]],
                 [[symbol_to_oxinum.keys(),
                   symbol_to_oxinum.values()]]))

        atom_site_type_symbol = []
        atom_site_symmetry_multiplicity = []
        atom_site_fract_x = []
        atom_site_fract_y = []
        atom_site_fract_z = []
        atom_site_attached_hydrogens = []
        atom_site_B_iso_or_equiv = []
        atom_site_label = []
        atom_site_occupancy = []
        count = 1
        for site in struct:
            for sp, occu in site.species_and_occu.items():
                atom_site_type_symbol.append(str(sp))
                atom_site_symmetry_multiplicity.append("1")
                atom_site_fract_x.append("{0:f}".format(site.a))
                atom_site_fract_y.append("{0:f}".format(site.b))
                atom_site_fract_z.append("{0:f}".format(site.c))
                atom_site_attached_hydrogens.append("0")
                atom_site_B_iso_or_equiv.append(".")
                atom_site_label.append("{}{}".format(sp.symbol, count))
                atom_site_occupancy.append(str(occu))
                count += 1

        block["_atom_site_type_symbol"] = atom_site_type_symbol
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_label": atom_site_label})
        block.AddToLoop("_atom_site_type_symbol", {
            "_atom_site_symmetry_multiplicity":
            atom_site_symmetry_multiplicity
        })
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_fract_x": atom_site_fract_x})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_fract_y": atom_site_fract_y})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_fract_z": atom_site_fract_z})
        block.AddToLoop(
            "_atom_site_type_symbol",
            {"_atom_site_attached_hydrogens": atom_site_attached_hydrogens})
        block.AddToLoop(
            "_atom_site_type_symbol",
            {"_atom_site_B_iso_or_equiv": atom_site_B_iso_or_equiv})
        block.AddToLoop("_atom_site_type_symbol",
                        {"_atom_site_occupancy": atom_site_occupancy})

        self._cf = CifFile.CifFile()
        # AJ says: CIF Block names cannot be more than 75 characters or you
        # get an Exception
        self._cf[comp.reduced_formula[0:74]] = block
示例#19
0
    def get_element_profile(self, element, comp, comp_tol=1e-5):
        """
        Provides the element evolution data for a composition.
        For example, can be used to analyze Li conversion voltages by varying
        uLi and looking at the phases formed. Also can be used to analyze O2
        evolution by varying uO2.

        Args:
            element:
                An element. Must be in the phase diagram.
            comp:
                A Composition
            comp_tol:
                The tolerance to use when calculating decompositions. Phases
                with amounts less than this tolerance are excluded. Defaults to
                1e-5.

        Returns:
            Evolution data as a list of dictionaries of the following format:
            [ {'chempot': -10.487582010000001, 'evolution': -2.0,
            'reaction': Reaction Object], ...]
        """
        if element not in self._pd.elements:
            raise ValueError("get_transition_chempots can only be called with"
                             " elements in the phase diagram.")
        chempots = self.get_transition_chempots(element)
        stable_entries = self._pd.stable_entries
        gccomp = Composition(
            {el: amt
             for el, amt in comp.items() if el != element})
        elref = self._pd.el_refs[element]
        elcomp = Composition.from_formula(element.symbol)
        prev_decomp = []
        evolution = []

        def are_same_decomp(decomp1, decomp2):
            for comp in decomp2:
                if comp not in decomp1:
                    return False
            return True

        for c in chempots:
            gcpd = GrandPotentialPhaseDiagram(stable_entries,
                                              {element: c - 0.01},
                                              self._pd.elements)
            analyzer = PDAnalyzer(gcpd)
            gcdecomp = analyzer.get_decomposition(gccomp)
            decomp = [
                gcentry.original_entry.composition
                for gcentry, amt in gcdecomp.items() if amt > comp_tol
            ]
            decomp_entries = [
                gcentry.original_entry for gcentry, amt in gcdecomp.items()
                if amt > comp_tol
            ]

            if not are_same_decomp(prev_decomp, decomp):
                if elcomp not in decomp:
                    decomp.insert(0, elcomp)
                rxn = Reaction([comp], decomp)
                rxn.normalize_to(comp)
                prev_decomp = decomp
                amt = -rxn.coeffs[rxn.all_comp.index(elcomp)]
                evolution.append({
                    'chempot': c,
                    'evolution': amt,
                    'element_reference': elref,
                    'reaction': rxn,
                    'entries': decomp_entries
                })

        return evolution