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)
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))
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"))
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)
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)
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"), )
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)
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"))
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)