def test_from_string(self):
     rxn = BalancedReaction({
         Composition("Li"): 4,
         Composition("O2"): 1
     }, {Composition("Li2O"): 2})
     self.assertEqual(rxn,
                      BalancedReaction.from_string("4 Li + O2 -> 2Li2O"))
    def test_remove_spectator_species(self):
        rxn = BalancedReaction(
            {
                Composition("Li"): 4,
                Composition("O2"): 1,
                Composition('Na'): 1
            }, {
                Composition("Li2O"): 2,
                Composition('Na'): 1
            },
            remove_spectator_species=True)

        self.assertTrue(Composition('Na') not in rxn.all_comp)

        rxn2 = BalancedReaction(
            {
                Composition("Li"): 4,
                Composition("O2"): 1,
                Composition('Na'): 1
            }, {
                Composition("Li2O"): 2,
                Composition('Na'): 1
            },
            remove_spectator_species=False)

        self.assertTrue(Composition('Na') in rxn2.all_comp)
        self.assertTrue(
            abs(rxn2.get_coeff(Composition('Na'))) < Reaction.TOLERANCE)
예제 #3
0
 def test_to_from_dict(self):
     rct = {Composition("K2SO4"): 3, Composition("Na2S"): 1, Composition("Li"): 24}
     prod = {Composition("KNaS"): 2, Composition("K2S"): 2, Composition("Li2O"): 12}
     rxn = BalancedReaction(rct, prod)
     d = rxn.as_dict()
     new_rxn = BalancedReaction.from_dict(d)
     for comp in new_rxn.all_comp:
         self.assertEqual(new_rxn.get_coeff(comp), rxn.get_coeff(comp))
예제 #4
0
 def test_to_from_dict(self):
     rct = {Composition("K2SO4"): 3, Composition("Na2S"): 1, Composition("Li"): 24}
     prod = {Composition("KNaS"): 2, Composition("K2S"): 2, Composition("Li2O"): 12}
     rxn = BalancedReaction(rct, prod)
     d = rxn.as_dict()
     new_rxn = BalancedReaction.from_dict(d)
     for comp in new_rxn.all_comp:
         self.assertEqual(new_rxn.get_coeff(comp), rxn.get_coeff(comp))
예제 #5
0
    def test_from_string(self):
        rxn = BalancedReaction({Composition("Li"): 4, Composition("O2"): 1}, {Composition("Li2O"): 2})
        self.assertEqual(rxn, BalancedReaction.from_string("4 Li + O2 -> 2Li2O"))

        rxn = BalancedReaction(
            {Composition("Li(NiO2)3"): 1}, {Composition("O2"): 0.5, Composition("Li(NiO2)2"): 1, Composition("NiO"): 1}
        )

        self.assertEqual(rxn, BalancedReaction.from_string("1.000 Li(NiO2)3 -> 0.500 O2 + 1.000 Li(NiO2)2 + 1.000 NiO"))
예제 #6
0
 def test_to_from_dict(self):
     rct = {Composition('K2SO4'): 3,
            Composition('Na2S'): 1, Composition('Li'): 24}
     prod = {Composition('KNaS'): 2, Composition('K2S'): 2,
             Composition('Li2O'): 12}
     rxn = BalancedReaction(rct, prod)
     d = rxn.to_dict
     new_rxn = BalancedReaction.from_dict(d)
     for comp in new_rxn.all_comp:
         self.assertEqual(new_rxn.get_coeff(comp), rxn.get_coeff(comp))
    def test_remove_spectator_species(self):
        rxn = BalancedReaction({Composition("Li"): 4, Composition("O2"): 1, Composition('Na'): 1},
                               {Composition("Li2O"): 2, Composition('Na'): 1},
                               remove_spectator_species=True)

        self.assertTrue(Composition('Na') not in rxn.all_comp)

        rxn2 = BalancedReaction({Composition("Li"): 4, Composition("O2"): 1, Composition('Na'): 1},
                                {Composition("Li2O"): 2, Composition('Na'): 1},
                                remove_spectator_species=False)

        self.assertTrue(Composition('Na') in rxn2.all_comp)
        self.assertTrue(abs(rxn2.get_coeff(Composition('Na'))) < Reaction.TOLERANCE)
    def test_init(self):
        rct = {
            Composition('K2SO4'): 3,
            Composition('Na2S'): 1,
            Composition('Li'): 24
        }
        prod = {
            Composition('KNaS'): 2,
            Composition('K2S'): 2,
            Composition('Li2O'): 12
        }
        rxn = BalancedReaction(rct, prod)
        self.assertIsNotNone(str(rxn))

        # Test unbalanced exception
        rct = {
            Composition('K2SO4'): 1,
            Composition('Na2S'): 1,
            Composition('Li'): 24
        }
        prod = {
            Composition('KNaS'): 2,
            Composition('K2S'): 2,
            Composition('Li2O'): 12
        }
        self.assertRaises(ReactionError, BalancedReaction, rct, prod)
 def test_to_from_dict(self):
     rct = {
         Composition('K2SO4'): 3,
         Composition('Na2S'): 1,
         Composition('Li'): 24
     }
     prod = {
         Composition('KNaS'): 2,
         Composition('K2S'): 2,
         Composition('Li2O'): 12
     }
     rxn = BalancedReaction(rct, prod)
     d = rxn.to_dict
     new_rxn = BalancedReaction.from_dict(d)
     for comp in new_rxn.all_comp:
         self.assertEqual(new_rxn.get_coeff(comp), rxn.get_coeff(comp))
    def test_init(self):
        rct = {
            Composition('K2SO4'): 3,
            Composition('Na2S'): 1,
            Composition('Li'): 24
        }
        prod = {
            Composition('KNaS'): 2,
            Composition('K2S'): 2,
            Composition('Li2O'): 12
        }
        rxn = BalancedReaction(rct, prod)
        self.assertEquals(
            str(rxn),
            '24.000 Li + 3.000 K2SO4 + 1.000 Na2S -> 2.000 KNaS + 12.000 Li2O + 2.000 K2S'
        )

        #Test unbalanced exception
        rct = {
            Composition('K2SO4'): 1,
            Composition('Na2S'): 1,
            Composition('Li'): 24
        }
        prod = {
            Composition('KNaS'): 2,
            Composition('K2S'): 2,
            Composition('Li2O'): 12
        }
        self.assertRaises(ReactionError, BalancedReaction, rct, prod)
예제 #11
0
    def test_remove_spectator_species(self):
        rxn = BalancedReaction(
            {Composition("Li"): 4, Composition("O2"): 1, Composition("Na"): 1},
            {Composition("Li2O"): 2, Composition("Na"): 1},
        )

        self.assertTrue(Composition("Na") not in rxn.all_comp)
예제 #12
0
    def test_from_string(self):
        rxn = BalancedReaction({Composition("Li"): 4, Composition("O2"): 1}, {Composition("Li2O"): 2})
        self.assertEqual(rxn, BalancedReaction.from_string("4 Li + O2 -> 2Li2O"))

        rxn = BalancedReaction(
            {Composition("Li(NiO2)3"): 1},
            {
                Composition("O2"): 0.5,
                Composition("Li(NiO2)2"): 1,
                Composition("NiO"): 1,
            },
        )

        self.assertEqual(
            rxn,
            BalancedReaction.from_string("1.000 Li(NiO2)3 -> 0.500 O2 + 1.000 Li(NiO2)2 + 1.000 NiO"),
        )
예제 #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") * N_A * 1000
        licomp = Composition(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) > 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 range(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 range(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(cls,
                   step1,
                   step2,
                   normalization_els,
                   framework_formula=None):
        """
        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
        working_ion_valence = max(Element(working_ion).oxidation_states)
        voltage = (-step1["chempot"] +
                   working_ion_entry.energy_per_atom) / working_ion_valence
        mAh = ((step2["evolution"] - step1["evolution"]) *
               Charge(1, "e").to("C") * Time(1, "s").to("h") * N_A * 1000 *
               working_ion_valence)
        licomp = Composition(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) > 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 range(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 range(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 cls(
            rxn=rxn,
            voltage=voltage,
            mAh=mAh,
            vol_charge=vol_charge,
            vol_discharge=vol_discharge,
            mass_charge=mass_charge,
            mass_discharge=mass_discharge,
            frac_charge=frac_charge,
            frac_discharge=frac_discharge,
            entries_charge=entries_charge,
            entries_discharge=entries_discharge,
            working_ion_entry=working_ion_entry,
            _framework_formula=framework_formula,
        )
 def test_from_string(self):
     rxn = BalancedReaction({Composition("Li"): 4, Composition("O2"): 1},
                            {Composition("Li2O"): 2})
     self.assertEqual(rxn,
                      BalancedReaction.from_string("4 Li + O2 -> 2Li2O"))
예제 #16
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"]) \
            * ELECTRON_TO_AMPERE_HOURS * 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)