• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

materialsproject / pymatgen / 4075885785

pending completion
4075885785

push

github

Shyue Ping Ong
Merge branch 'master' of github.com:materialsproject/pymatgen

96 of 96 new or added lines in 27 files covered. (100.0%)

81013 of 102710 relevant lines covered (78.88%)

0.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.39
/pymatgen/apps/battery/tests/test_conversion_battery.py
1
# Copyright (c) Pymatgen Development Team.
2
# Distributed under the terms of the MIT License.
3

4

5
from __future__ import annotations
1✔
6

7
import json
1✔
8
import os
1✔
9
import unittest
1✔
10

11
from monty.json import MontyDecoder
1✔
12
from pytest import approx
1✔
13

14
from pymatgen.apps.battery.conversion_battery import (
1✔
15
    ConversionElectrode,
16
    ConversionVoltagePair,
17
)
18
from pymatgen.core.composition import Composition
1✔
19
from pymatgen.util.testing import PymatgenTest
1✔
20

21

22
class ConversionElectrodeTest(unittest.TestCase):
1✔
23
    def setUp(self):
1✔
24
        self.formulas = ["LiCoO2", "FeF3", "MnO2"]
1✔
25
        self.conversion_eletrodes = {}
1✔
26
        for f in self.formulas:
1✔
27
            with open(os.path.join(PymatgenTest.TEST_FILES_DIR, f + "_batt.json")) as fid:
1✔
28
                entries = json.load(fid, cls=MontyDecoder)
1✔
29
            if f in ["LiCoO2", "FeF3"]:
1✔
30
                working_ion = "Li"
1✔
31
            elif f in ["MnO2"]:
1✔
32
                working_ion = "Mg"
1✔
33
            c = ConversionElectrode.from_composition_and_entries(
1✔
34
                Composition(f), entries, working_ion_symbol=working_ion
35
            )
36
            self.conversion_eletrodes[f] = {"working_ion": working_ion, "CE": c}
1✔
37

38
        self.expected_properties = {
1✔
39
            "LiCoO2": {
40
                "average_voltage": 2.26940307125,
41
                "capacity_grav": 903.19752911225669,
42
                "capacity_vol": 2903.35804724,
43
                "specific_energy": 2049.7192465127678,
44
                "energy_density": 6588.8896693479574,
45
            },
46
            "FeF3": {
47
                "average_voltage": 3.06179925889,
48
                "capacity_grav": 601.54508701578118,
49
                "capacity_vol": 2132.2069115142394,
50
                "specific_energy": 1841.8103016131706,
51
                "energy_density": 6528.38954147,
52
            },
53
            "MnO2": {
54
                "average_voltage": 1.7127027687901726,
55
                "capacity_grav": 790.9142070034802,
56
                "capacity_vol": 3543.202003526853,
57
                "specific_energy": 1354.6009522103434,
58
                "energy_density": 6068.451881823329,
59
            },
60
        }
61

62
        # expected composite upon discharge process, of which entry object has been simplified to reduced formula
63
        self.expected_composite = {
1✔
64
            "LiCoO2": {
65
                "entries_charge": [["CoO2"], ["Li(CoO2)2"], ["LiCoO2"], ["Li6CoO4", "CoO"], ["Li6CoO4", "Co"]],
66
                "entries_discharge": [["Li(CoO2)2"], ["LiCoO2"], ["Li6CoO4", "CoO"], ["Li6CoO4", "Co"], ["Co", "Li2O"]],
67
            },
68
            "FeF3": {
69
                "entries_charge": [["FeF3"], ["FeF2", "LiF"]],
70
                "entries_discharge": [["FeF2", "LiF"], ["Fe", "LiF"]],
71
            },
72
            "MnO2": {"entries_charge": [["MnO2"]], "entries_discharge": [["Mn", "MgO"]]},
73
        }
74

75
    def test_init(self):
1✔
76
        # both 'LiCoO2' and "FeF3" are using Li+ as working ion; MnO2 is for the multivalent Mg2+ ion
77
        for f in self.formulas:
1✔
78
            c = self.conversion_eletrodes[f]["CE"]
1✔
79

80
            assert len(c.get_sub_electrodes(True)) == c.num_steps
1✔
81
            assert len(c.get_sub_electrodes(False)) == sum(range(1, c.num_steps + 1))
1✔
82
            assert str(c) is not None
1✔
83
            p = self.expected_properties[f]
1✔
84

85
            for k, v in p.items():
1✔
86
                assert getattr(c, "get_" + k)() == approx(v, abs=1e-2)
1✔
87

88
            assert c.get_summary_dict(True) is not None
1✔
89

90
            # try to export/import a voltage pair via a dict
91
            pair = c.voltage_pairs[0]
1✔
92
            d = pair.as_dict()
1✔
93
            pair2 = ConversionVoltagePair.from_dict(d)
1✔
94
            for prop in ["voltage", "mass_charge", "mass_discharge"]:
1✔
95
                assert getattr(pair, prop) == getattr(pair2, prop), 2
1✔
96

97
            # try to create an electrode from a dict and test methods
98
            d = c.as_dict()
1✔
99
            electrode = ConversionElectrode.from_dict(d)
1✔
100
            for k, v in p.items():
1✔
101
                assert getattr(electrode, "get_" + k)() == approx(v, abs=1e-2)
1✔
102

103
    def test_summary(self):
1✔
104
        kmap = {"specific_energy": "energy_grav", "energy_density": "energy_vol"}
1✔
105
        for f in self.formulas:
1✔
106
            c = self.conversion_eletrodes[f]["CE"]
1✔
107
            d = c.get_summary_dict()
1✔
108
            p = self.expected_properties[f]
1✔
109
            for k, v in p.items():
1✔
110
                summary_key = kmap.get(k, k)
1✔
111
                assert d[summary_key] == approx(v, abs=1e-2)
1✔
112

113
    def test_composite(self):
1✔
114
        # check entries in charged/discharged state
115
        for formula in self.formulas:
1✔
116
            CE = self.conversion_eletrodes[formula]["CE"]
1✔
117
            for step, vpair in enumerate(CE.voltage_pairs):
1✔
118
                # entries_charge/entries_discharge attributes should return entries equal with the expected
119
                composite_dict = self.expected_composite[formula]
1✔
120
                for attri in ["entries_charge", "entries_discharge"]:
1✔
121
                    # composite at each discharge step, of which entry object is simplified to reduced formula
122
                    entries_formula_list = [entry.composition.reduced_formula for entry in getattr(vpair, attri)]
1✔
123
                    assert entries_formula_list == composite_dict[attri][step]
1✔
124

125

126
if __name__ == "__main__":
1✔
127
    unittest.main()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc