Ejemplo n.º 1
0
    def test_calculate_energy(self):

        reactants = [Composition.from_formula("MgO"), Composition.from_formula("Al2O3")]
        products = [Composition.from_formula("MgAl2O4")]
        energies = {Composition.from_formula("MgO"):-0.1, Composition.from_formula("Al2O3"):-0.2, Composition.from_formula("MgAl2O4"):-0.5}
        rxn = Reaction(reactants, products)
        self.assertEquals(str(rxn), "1.000 MgO + 1.000 Al2O3 -> 1.000 MgAl2O4", "Wrong reaction obtained!")
        self.assertEquals(rxn.normalized_repr, "MgO + Al2O3 -> MgAl2O4", "Wrong normalized reaction obtained!")
        self.assertAlmostEquals(rxn.calculate_energy(energies), -0.2, 5)
Ejemplo n.º 2
0
 def test_get_atoms(self):
     if not aio.ase_loaded:
         raise SkipTest("ASE not present. Skipping...")
     p = Poscar.from_file(os.path.join(test_dir, 'POSCAR'))
     structure = p.struct
     atoms = aio.AseAtomsAdaptor.get_atoms(structure)
     ase_composition = Composition.from_formula(atoms.get_name())
     self.assertEqual(ase_composition, structure.composition)
Ejemplo n.º 3
0
    def test_init(self):
        rct = {Composition.from_formula('K2SO4'):3, Composition.from_formula('Na2S'):1, Composition.from_formula('Li'):24}
        prod = {Composition.from_formula('KNaS'): 2, Composition.from_formula('K2S'):2, Composition.from_formula('Li2O'):12}
        rxn = BalancedReaction(rct, prod)
        self.assertEquals(str(rxn), "24.000 Li + 1.000 Na2S + 3.000 K2SO4 -> 12.000 Li2O + 2.000 K2S + 2.000 KNaS")

        #Test unbalanced exception
        rct = {Composition.from_formula('K2SO4'):1, Composition.from_formula('Na2S'):1, Composition.from_formula('Li'):24}
        prod = {Composition.from_formula('KNaS'): 2, Composition.from_formula('K2S'):2, Composition.from_formula('Li2O'):12}
        self.assertRaises(ReactionError, BalancedReaction, rct, prod)
Ejemplo n.º 4
0
    def test_init(self):
        filepath = os.path.join(test_dir, 'POSCAR')
        poscar = Poscar.from_file(filepath)
        comp = poscar.struct.composition
        self.assertEqual(comp, Composition.from_formula("Fe4P4O16"))

        #Vasp 4 type with symbols at the end.
        poscar_string = """Test1
1.0
3.840198 0.000000 0.000000
1.920099 3.325710 0.000000
0.000000 -2.217138 3.135509
1 1
direct
0.000000 0.000000 0.000000 Si
0.750000 0.500000 0.750000 F"""
        poscar = Poscar.from_string(poscar_string)
        self.assertEqual(poscar.struct.composition, Composition.from_formula("SiF"))

        #Vasp 4 tyle file with default names, i.e. no element symbol found.
        poscar_string = """Test2
1.0
3.840198 0.000000 0.000000
1.920099 3.325710 0.000000
0.000000 -2.217138 3.135509
1 1
direct
0.000000 0.000000 0.000000
0.750000 0.500000 0.750000"""
        poscar = Poscar.from_string(poscar_string)
        self.assertEqual(poscar.struct.composition, Composition.from_formula("HHe"))

        #Vasp 4 tyle file with default names, i.e. no element symbol found.
        poscar_string = """Test3
1.0
3.840198 0.000000 0.000000
1.920099 3.325710 0.000000
0.000000 -2.217138 3.135509
1 1
Selective dynamics
direct
0.000000 0.000000 0.000000 T T T Si
0.750000 0.500000 0.750000 F F F O"""
        poscar = Poscar.from_string(poscar_string)
        self.assertEqual(poscar.selective_dynamics, [[True, True, True], [False, False, False]])
Ejemplo n.º 5
0
def ion_or_solid_comp_object(formula):
    """
    Returns either an ion object or composition object given
    a formula.

    Args:
        formula: String formula. Eg. of ion: NaOH(aq), Na[+];
            Eg. of solid: Fe2O3(s), Fe(s), Na2O

    Returns:
        Composition/Ion object
    """
    m = re.search(r"\[([^\[\]]+)\]|\(aq\)", formula)
    if m:
        comp_obj = Ion.from_formula(formula)
    elif re.search(r"\(s\)", formula):
        comp_obj = Composition.from_formula(formula[:-3])
    else:
        comp_obj = Composition.from_formula(formula)
    return comp_obj
Ejemplo n.º 6
0
 def test_indeterminate_formula(self):
     correct_formulas = []
     correct_formulas.append(["Co1"])
     correct_formulas.append(["Co1", "C1 O1"])
     correct_formulas.append(["Co2 O3", "C1 O5"])
     correct_formulas.append(["N1 Ca1 Lu1", "U1 Al1 C1 N1"])
     correct_formulas.append(["N1 Ca1 Lu1", "U1 Al1 C1 N1"])
     correct_formulas.append(["Li1 Co1 P2 N1 O10", "Li1 P2 C1 N1 O11", "Li1 Co1 Po8 N1 O2", "Li1 Po8 C1 N1 O3"])
     correct_formulas.append(["Co2 P4 O4", "P4 C2 O6", "Co2 Po4", "Po4 C2 O2"])
     correct_formulas.append([])
     for i, c in enumerate(correct_formulas):
         self.assertEqual([Composition.from_formula(comp) for comp in c], self.indeterminate_comp[i])
Ejemplo n.º 7
0
    def test_products_reactants(self):
        reactants = [Composition.from_formula("Li3Fe2(PO4)3"), Composition.from_formula("Fe2O3"), Composition.from_formula("O2")]
        products = [Composition.from_formula("LiFePO4")]
        energies = {Composition.from_formula("Li3Fe2(PO4)3"):-0.1, Composition.from_formula("Fe2O3"):-0.2, Composition.from_formula("O2"):-0.2, Composition.from_formula("LiFePO4"):-0.5}
        rxn = Reaction(reactants, products)

        self.assertIn(Composition.from_formula("O2"), rxn.products, "O not in products!")
        self.assertIn(Composition.from_formula("Li3Fe2(PO4)3"), rxn.reactants, "Li3Fe2(PO4)4 not in reactants!")
        self.assertEquals(str(rxn), "0.333 Li3Fe2(PO4)3 + 0.167 Fe2O3 -> 0.250 O2 + 1.000 LiFePO4", "Wrong reaction obtained!")
        self.assertEquals(rxn.normalized_repr, "4 Li3Fe2(PO4)3 + 2 Fe2O3 -> 3 O2 + 12 LiFePO4", "Wrong normalized reaction obtained!")
        self.assertAlmostEquals(rxn.calculate_energy(energies), -0.48333333, 5)
Ejemplo n.º 8
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 %s" % (-scaled_coeff, comp.reduced_formula))
            elif scaled_coeff > 0:
                product_str.append("%.3f %s" % (scaled_coeff, comp.reduced_formula))

        return " + ".join(reactant_str) + " -> " + " + ".join(product_str)
Ejemplo n.º 9
0
    def get_element_profile(self, element, comp):
        """
        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
        
        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)
            decomp = [gcentry.original_entry.composition for gcentry, amt in analyzer.get_decomposition(gccomp).items() if amt > 1e-5]
            decomp_entries = [gcentry.original_entry for gcentry, amt in analyzer.get_decomposition(gccomp).items() if amt > 1e-5]

            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
                evolution.append({'chempot':c, 'evolution' :-rxn.coeffs[rxn.all_comp.index(elcomp)], 'element_reference': elref, 'reaction':rxn, 'entries':decomp_entries})

        return evolution
Ejemplo n.º 10
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.indeterminate_comp = list()
        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"))
Ejemplo n.º 11
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.from_formula(comp.formula)
        block['_symmetry_space_group_name_H-M'] = 'P 1'
        block['_cell_length_a'] = str(latt.a)
        block['_cell_length_b'] = str(latt.b)
        block['_cell_length_c'] = str(latt.c)
        block['_cell_angle_alpha'] = str(latt.alpha)
        block['_cell_angle_beta'] = str(latt.beta)
        block['_cell_angle_gamma'] = str(latt.gamma)
        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
        symbol_to_oxinum = dict()
        try:
            symbol_to_oxinum = {str(el):el.oxi_state for el in comp.elements}
        except:
            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(str('{0:f}'.format(site.a)))
                atom_site_fract_y.append(str('{0:f}'.format(site.b)))
                atom_site_fract_z.append(str('{0:f}'.format(site.c)))
                atom_site_attached_hydrogens.append('0')
                atom_site_B_iso_or_equiv.append('.')
                atom_site_label.append(str(sp.symbol) + str(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()
        self._cf[comp.reduced_formula] = block
Ejemplo n.º 12
0
 def test_get_decomposition(self):
     for entry in self.pd.stable_entries:
         self.assertEquals(len(self.analyzer.get_decomposition(entry.composition)), 1, "Stable composition should have only 1 decomposition!")
     dim = len(self.pd.elements)
     for entry in self.pd.all_entries:
         ndecomp = len(self.analyzer.get_decomposition(entry.composition))
         self.assertTrue(ndecomp > 0 and ndecomp <= dim, "The number of decomposition phases can at most be equal to the number of components.")
     
     #Just to test decomp for a ficitious composition
     ansdict = {entry.composition.formula: amt for entry, amt in self.analyzer.get_decomposition(Composition.from_formula("Li3Fe7O11")).items()}
     expected_ans = {"Fe2 O2" : 0.0952380952380949, "Li1 Fe1 O2": 0.5714285714285714, "Fe6 O8": 0.33333333333333393}
     for k, v in expected_ans.items():
         self.assertAlmostEqual(ansdict[k], v)
Ejemplo n.º 13
0
 def test_normalize_to(self):
     products = [Composition.from_formula("Fe"), Composition.from_formula("O2")]
     reactants = [Composition.from_formula("Fe2O3")]
     rxn = Reaction(reactants, products)
     rxn.normalize_to(Composition.from_formula("Fe"), 3)
     self.assertEquals(str(rxn), "1.500 Fe2O3 -> 3.000 Fe + 2.250 O2", "Wrong reaction obtained!")
Ejemplo n.º 14
0
    def test_init(self):

        reactants = [Composition.from_formula("Fe"), Composition.from_formula("O2")]
        products = [Composition.from_formula("Fe2O3")]
        rxn = Reaction(reactants, products)
        self.assertEquals(str(rxn), "2.000 Fe + 1.500 O2 -> 1.000 Fe2O3", "Wrong reaction obtained!")
        self.assertEquals(rxn.normalized_repr, "4 Fe + 3 O2 -> 2 Fe2O3", "Wrong normalized reaction obtained!")

        reactants = [Composition.from_formula("Fe"), Composition.from_formula("O"), Composition.from_formula("Mn"), Composition.from_formula("P")]
        products = [Composition.from_formula("FeP"), Composition.from_formula("MnO")]
        rxn = Reaction(reactants, products)
        self.assertEquals(str(rxn), "1.000 Fe + 0.500 O2 + 1.000 Mn + 1.000 P -> 1.000 FeP + 1.000 MnO", "Wrong reaction obtained!")
        self.assertEquals(rxn.normalized_repr, "2 Fe + O2 + 2 Mn + 2 P -> 2 FeP + 2 MnO", "Wrong normalized reaction obtained!")
        reactants = [Composition.from_formula("FePO4")]
        products = [Composition.from_formula("FePO4")]

        rxn = Reaction(reactants, products)
        self.assertEquals(str(rxn), "1.000 FePO4 -> 1.000 FePO4", "Wrong reaction obtained!")

        products = [Composition.from_formula("Ti2 O4"), Composition.from_formula("O1")]
        reactants = [Composition.from_formula("Ti1 O2")]
        rxn = Reaction(reactants, products)
        self.assertEquals(str(rxn), "2.000 TiO2 -> 2.000 TiO2", "Wrong reaction obtained!")

        reactants = [Composition.from_formula("FePO4"), Composition.from_formula("Li")]
        products = [Composition.from_formula("LiFePO4")]
        rxn = Reaction(reactants, products)
        self.assertEquals(str(rxn), "1.000 FePO4 + 1.000 Li -> 1.000 LiFePO4", "Wrong reaction obtained!")

        reactants = [Composition.from_formula("MgO")]
        products = [Composition.from_formula("MgO")]

        rxn = Reaction(reactants, products)
        self.assertEquals(str(rxn), "1.000 MgO -> 1.000 MgO", "Wrong reaction obtained!")

        reactants = [Composition.from_formula("Mg")]
        products = [Composition.from_formula("Mg")]

        rxn = Reaction(reactants, products)
        self.assertEquals(str(rxn), "1.000 Mg -> 1.000 Mg", "Wrong reaction obtained!")

        reactants = [Composition.from_formula("FePO4"), Composition.from_formula("LiPO3")]
        products = [Composition.from_formula("LiFeP2O7")]

        rxn = Reaction(reactants, products)
        self.assertEquals(str(rxn), "1.000 FePO4 + 1.000 LiPO3 -> 1.000 LiFeP2O7", "Wrong reaction obtained!")

        reactants = [Composition.from_formula("Na"), Composition.from_formula("K2O")]
        products = [Composition.from_formula("Na2O"), Composition.from_formula("K")]
        rxn = Reaction(reactants, products)
        self.assertEquals(str(rxn), "1.000 Na + 0.500 K2O -> 0.500 Na2O + 1.000 K", "Wrong reaction obtained!")

        # Test for an old bug which has a problem when excess product is defined.
        products = [Composition.from_formula("FePO4"), Composition.from_formula("O")]
        reactants = [Composition.from_formula("FePO4")]
        rxn = Reaction(reactants, products)

        self.assertEquals(str(rxn), "1.000 FePO4 -> 1.000 FePO4", "Wrong reaction obtained!")

        products = map(Composition.from_formula, ['La8Ti8O12', 'O2', 'LiCrO2'])
        reactants = [Composition.from_formula('LiLa3Ti3CrO12')]
        rxn = Reaction(reactants, products)
        self.assertEquals(str(rxn), "1.000 LiLa3Ti3CrO12 -> 1.500 La2Ti2O3 + 2.750 O2 + 1.000 LiCrO2", "Wrong reaction obtained!")
Ejemplo n.º 15
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")
Ejemplo n.º 16
0
 def test_reduced_composition(self):
     correct_reduced_formulas = ['Li3Fe2(PO4)3', 'Li3FePO5', 'LiMn2O4', 'Li2O2', 'Li3Fe2(MoO4)3', 'Li3Fe2P6(C5O27)2', 'Li1.5Si0.5']
     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]))