示例#1
0
    def process_item(self, item):
        """
        Read the entries from the thermo database and group them based on the reduced composition
        of the framework material (without working ion).
        Args:
            chemsys(string): the chemical system string to be queried
        returns:
            (chemsys, [group]): entry contains a list of entries the materials together by composition
        """
        # sort the entries intro subgroups
        # then perform PD analysis
        all_entries = item['all_entries']
        pd_ents = item['pd_ents']
        phdi = PhaseDiagram(pd_ents)

        # The working ion entries
        ents_wion = list(
            filter(
                lambda x: x.composition.get_integer_formula_and_factor()[0] ==
                self.working_ion, pd_ents))
        self.working_ion_entry = min(ents_wion,
                                     key=lambda e: e.energy_per_atom)
        assert (self.working_ion_entry != None)

        grouped_entries = list(self.get_sorted_subgroups(all_entries))
        docs = []  # results

        for group in grouped_entries:
            self.logger.debug(
                f"Grouped entries in all sandboxes {', '.join([en.name for en in group])}"
            )
            for en in group:
                # skip this d_muO2 stuff if you do note have oxygen
                if Element('O') in en.composition.elements:
                    d_muO2 = [{
                        'reaction': str(itr['reaction']),
                        'chempot': itr['chempot'],
                        'evolution': itr['evolution']
                    } for itr in phdi.get_element_profile('O', en.composition)]
                else:
                    d_muO2 = None
                en.data['muO2'] = d_muO2
                en.data['decomposition_energy'] = phdi.get_e_above_hull(en)

            # sort out the sandboxes
            # for each sandbox core+sandbox will both contribute entries
            all_sbx = [ent.data['sbxn'] for ent in group]
            all_sbx = set(chain.from_iterable(all_sbx))
            self.logger.debug(f"All sandboxes {', '.join(list(all_sbx))}")

            for isbx in all_sbx:
                group_sbx = list(
                    filter(
                        lambda ent: (isbx in ent.data['sbxn']) or (ent.data[
                            'sbxn'] == ['core']), group))
                # Need more than one level of lithiation to define a electrode material
                if len(group_sbx) == 1:
                    continue
                self.logger.debug(
                    f"Grouped entries in sandbox {isbx} -- {', '.join([en.name for en in group_sbx])}"
                )
                try:
                    result = InsertionElectrode(group_sbx,
                                                self.working_ion_entry)
                    assert (len(result._stable_entries) > 1)
                except:
                    self.logger.warn(
                        f"Not able to generate a  entries in sandbox {isbx} using the following entires-- {', '.join([en.entry_id for en in group_sbx])}"
                    )
                    continue

                spacegroup = SpacegroupAnalyzer(
                    result.get_stable_entries(
                        charge_to_discharge=True)[0].structure)
                d = result.as_dict_summary()
                ids = [entry.entry_id for entry in result.get_all_entries()]
                lowest_id = sorted(ids, key=lambda x: x.split('-')[-1])[0]
                d['spacegroup'] = {
                    k: spacegroup._space_group_data[k]
                    for k in sg_fields
                }

                if isbx == 'core':
                    d['battid'] = lowest_id + '_' + self.working_ion
                else:
                    d['battid'] = lowest_id + '_' + self.working_ion + '_' + isbx
                # Only allow one sandbox value for each electrode
                d['sbxn'] = [isbx]

                docs.append(d)

        return docs
示例#2
0
class InsertionElectrodeTest(unittest.TestCase):
    def setUp(self):
        self.entry_Li = ComputedEntry("Li", -1.90753119)

        with open(os.path.join(test_dir, "LiTiO2_batt.json"), "r") as f:
            self.entries_LTO = json.load(f, cls=MontyDecoder)

        with open(os.path.join(test_dir, "MgVO_batt.json"), "r") as file:
            self.entries_MVO = json.load(file, cls=MontyDecoder)

        with open(os.path.join(test_dir, "Mg_batt.json"), "r") as file:
            self.entry_Mg = json.load(file, cls=MontyDecoder)

        self.ie_LTO = InsertionElectrode(self.entries_LTO, self.entry_Li)
        self.ie_MVO = InsertionElectrode(self.entries_MVO, self.entry_Mg)

    def test_voltage(self):
        #test basic voltage
        self.assertAlmostEqual(self.ie_LTO.max_voltage, 2.78583901, 3)
        self.assertAlmostEqual(self.ie_LTO.min_voltage, 0.89702381, 3)
        self.assertAlmostEqual(self.ie_LTO.get_average_voltage(), 1.84143141,
                               3)
        #test voltage range selectors
        self.assertAlmostEqual(self.ie_LTO.get_average_voltage(0, 1),
                               0.89702381, 3)
        self.assertAlmostEqual(self.ie_LTO.get_average_voltage(2, 3),
                               2.78583901, 3)
        #test non-existing voltage range
        self.assertAlmostEqual(self.ie_LTO.get_average_voltage(0, 0.1), 0, 3)
        self.assertAlmostEqual(self.ie_LTO.get_average_voltage(4, 5), 0, 3)

        self.assertAlmostEqual(self.ie_MVO.get_average_voltage(), 2.513767, 3)

    def test_capacities(self):
        #test basic capacity
        self.assertAlmostEqual(self.ie_LTO.get_capacity_grav(), 308.74865045,
                               3)
        self.assertAlmostEqual(self.ie_LTO.get_capacity_vol(), 1205.99391136,
                               3)

        #test capacity selector
        self.assertAlmostEqual(self.ie_LTO.get_capacity_grav(1, 3),
                               154.374325225, 3)

        #test alternate normalization option
        self.assertAlmostEqual(self.ie_LTO.get_capacity_grav(1, 3, False),
                               160.803169506, 3)
        self.assertIsNotNone(self.ie_LTO.as_dict_summary(True))

        self.assertAlmostEqual(self.ie_MVO.get_capacity_grav(), 281.845548242,
                               3)
        self.assertAlmostEqual(self.ie_MVO.get_capacity_vol(), 1145.80087994,
                               3)

    def test_get_instability(self):
        self.assertIsNone(self.ie_LTO.get_max_instability())
        self.assertAlmostEqual(self.ie_MVO.get_max_instability(),
                               0.7233711650000014)
        self.assertAlmostEqual(self.ie_MVO.get_min_instability(),
                               0.4913575099999994)

    def test_get_muO2(self):
        self.assertIsNone(self.ie_LTO.get_max_muO2())
        self.assertAlmostEqual(self.ie_MVO.get_max_muO2(), -4.93552791875)
        self.assertAlmostEqual(self.ie_MVO.get_min_muO2(), -11.06599657)

    def test_entries(self):
        #test that the proper number of sub-electrodes are returned
        self.assertEqual(len(self.ie_LTO.get_sub_electrodes(False, True)), 3)
        self.assertEqual(len(self.ie_LTO.get_sub_electrodes(True, True)), 2)

    def test_get_all_entries(self):
        self.ie_LTO.get_all_entries()

    def test_to_from_dict(self):
        d = self.ie_LTO.as_dict()
        ie = InsertionElectrode.from_dict(d)
        self.assertAlmostEqual(ie.max_voltage, 2.78583901, 3)
        self.assertAlmostEqual(ie.min_voltage, 0.89702381, 3)
        self.assertAlmostEqual(ie.get_average_voltage(), 1.84143141, 3)

        #Just to make sure json string works.
        json_str = json.dumps(self.ie_LTO, cls=MontyEncoder)
        ie = json.loads(json_str, cls=MontyDecoder)
        self.assertAlmostEqual(ie.max_voltage, 2.78583901, 3)
        self.assertAlmostEqual(ie.min_voltage, 0.89702381, 3)
        self.assertAlmostEqual(ie.get_average_voltage(), 1.84143141, 3)

    def test_voltage_pair(self):
        vpair = self.ie_LTO[0]
        self.assertAlmostEqual(vpair.voltage, 2.78583901)
        self.assertAlmostEqual(vpair.mAh, 13400.7411749, 2)
        self.assertAlmostEqual(vpair.mass_charge, 79.8658)
        self.assertAlmostEqual(vpair.mass_discharge, 83.3363)
        self.assertAlmostEqual(vpair.vol_charge, 37.553684467)
        self.assertAlmostEqual(vpair.vol_discharge, 37.917719932)
        self.assertAlmostEqual(vpair.frac_charge, 0.0)
        self.assertAlmostEqual(vpair.frac_discharge, 0.14285714285714285)
示例#3
0
    def process_item(self, item):
        """
        Read the entries from the thermo database and group them based on the reduced composition
        of the framework material (without working ion).
        Args:
            chemsys(string): the chemical system string to be queried
        returns:
            (chemsys, [group]): entry contains a list of entries the materials together by composition
        """
        # sort the entries intro subgroups
        # then perform PD analysis
        all_entries = item["all_entries"]
        pd_ents = item["pd_ents"]
        phdi = PhaseDiagram(pd_ents)

        # The working ion entries
        ents_wion = list(
            filter(
                lambda x: x.composition.get_integer_formula_and_factor()[0]
                == self.working_ion,
                pd_ents,
            )
        )
        self.working_ion_entry = min(ents_wion, key=lambda e: e.energy_per_atom)
        assert self.working_ion_entry != None

        grouped_entries = list(self.get_sorted_subgroups(all_entries))

        docs = []  # results

        for group in grouped_entries:
            self.logger.debug(
                f"Grouped entries in all sandboxes {', '.join([en.name for en in group])}"
            )
            for en in group:
                # skip this d_muO2 stuff if you do note have oxygen
                if Element("O") in en.composition.elements:
                    d_muO2 = [
                        {
                            "reaction": str(itr["reaction"]),
                            "chempot": itr["chempot"],
                            "evolution": itr["evolution"],
                        }
                        for itr in phdi.get_element_profile("O", en.composition)
                    ]
                else:
                    d_muO2 = None
                en.data["muO2"] = d_muO2
                en.data["decomposition_energy"] = phdi.get_e_above_hull(en)

            # sort out the sandboxes
            # for each sandbox core+sandbox will both contribute entries
            all_sbx = [ent.data["_sbxn"] for ent in group]
            all_sbx = set(chain.from_iterable(all_sbx))
            self.logger.debug(f"All sandboxes {', '.join(list(all_sbx))}")

            for isbx in all_sbx:
                group_sbx = list(
                    filter(
                        lambda ent: (isbx in ent.data["_sbxn"])
                        or (ent.data["_sbxn"] == ["core"]),
                        group,
                    )
                )
                self.logger.debug(
                    f"Grouped entries in sandbox {', '.join([en.name for en in group_sbx])}"
                )

                result = InsertionElectrode(group_sbx, self.working_ion_entry)

                spacegroup = SpacegroupAnalyzer(
                    result.get_stable_entries(charge_to_discharge=True)[0].structure
                )

                d = result.as_dict_summary()

                # d['stable_material_ids'] = [entry.entry_id
                #                        for entry in result.get_stable_entries()]
                # d['unstable_material_ids'] = [entry.entry_id
                #                             for entry in result.get_unstable_entries()]
                # d['stability_data'] = {entry.entry_id : entry.data['decomposition_energy']
                #                               for entry in result.get_all_entries()}
                # d['muO2_data'] = {entry.entry_id : entry.data['muO2']
                #                        for entry in result.get_all_entries()}

                # sort the ids based on value
                ids = [entry.entry_id for entry in result.get_all_entries()]
                lowest_id = sorted(ids, key=lambda x: x.split("-")[-1])[0]
                d["spacegroup"] = {
                    k: spacegroup._space_group_data[k] for k in sg_fields
                }

                if isbx == "core":
                    d["battid"] = lowest_id + "_" + self.working_ion
                else:
                    d["battid"] = lowest_id + "_" + self.working_ion + "_" + isbx
                # Only allow one sandbox value for each electrode
                d["_sbxn"] = [isbx]

                docs.append(d)

        return docs
class InsertionElectrodeTest(unittest.TestCase):

    def setUp(self):
        self.entry_Li = ComputedEntry("Li", -1.90753119)

        with open(os.path.join(test_dir, "LiTiO2_batt.json"), "r") as f:
            self.entries_LTO = json.load(f, cls=MontyDecoder)

        with open(os.path.join(test_dir, "MgVO_batt.json"), "r") as file:
            self.entries_MVO = json.load(file, cls=MontyDecoder)

        with open(os.path.join(test_dir, "Mg_batt.json"), "r") as file:
            self.entry_Mg = json.load(file, cls=MontyDecoder)


        self.ie_LTO = InsertionElectrode(self.entries_LTO, self.entry_Li)
        self.ie_MVO = InsertionElectrode(self.entries_MVO, self.entry_Mg)

    def test_voltage(self):
        #test basic voltage
        self.assertAlmostEqual(self.ie_LTO.max_voltage, 2.78583901, 3)
        self.assertAlmostEqual(self.ie_LTO.min_voltage, 0.89702381, 3)
        self.assertAlmostEqual(self.ie_LTO.get_average_voltage(), 1.84143141,
                               3)
        #test voltage range selectors
        self.assertAlmostEqual(self.ie_LTO.get_average_voltage(0, 1),
                               0.89702381, 3)
        self.assertAlmostEqual(self.ie_LTO.get_average_voltage(2, 3),
                               2.78583901, 3)
        #test non-existing voltage range
        self.assertAlmostEqual(self.ie_LTO.get_average_voltage(0, 0.1), 0, 3)
        self.assertAlmostEqual(self.ie_LTO.get_average_voltage(4, 5), 0, 3)

        self.assertAlmostEqual(self.ie_MVO.get_average_voltage(), 2.513767,3)



    def test_capacities(self):
        #test basic capacity
        self.assertAlmostEqual(self.ie_LTO.get_capacity_grav(), 308.74865045,
                               3)
        self.assertAlmostEqual(self.ie_LTO.get_capacity_vol(), 1205.99391136,
                               3)

        #test capacity selector
        self.assertAlmostEqual(self.ie_LTO.get_capacity_grav(1, 3),
                               154.374325225, 3)

        #test alternate normalization option
        self.assertAlmostEqual(self.ie_LTO.get_capacity_grav(1, 3, False),
                               160.803169506, 3)
        self.assertIsNotNone(self.ie_LTO.as_dict_summary(True))

        self.assertAlmostEqual(self.ie_MVO.get_capacity_grav(), 281.845548242, 3)
        self.assertAlmostEqual(self.ie_MVO.get_capacity_vol(), 1145.80087994, 3)



    def test_get_muO2(self):
        self.assertIsNone(self.ie_LTO.get_max_muO2())

    def test_entries(self):
        #test that the proper number of sub-electrodes are returned
        self.assertEqual(len(self.ie_LTO.get_sub_electrodes(False, True)), 3)
        self.assertEqual(len(self.ie_LTO.get_sub_electrodes(True, True)), 2)

    def test_get_all_entries(self):
        self.ie_LTO.get_all_entries()

    def test_to_from_dict(self):
        d = self.ie_LTO.as_dict()
        ie = InsertionElectrode.from_dict(d)
        self.assertAlmostEqual(ie.max_voltage, 2.78583901, 3)
        self.assertAlmostEqual(ie.min_voltage, 0.89702381, 3)
        self.assertAlmostEqual(ie.get_average_voltage(), 1.84143141, 3)

        #Just to make sure json string works.
        json_str = json.dumps(self.ie_LTO, cls=MontyEncoder)
        ie = json.loads(json_str, cls=MontyDecoder)
        self.assertAlmostEqual(ie.max_voltage, 2.78583901, 3)
        self.assertAlmostEqual(ie.min_voltage, 0.89702381, 3)
        self.assertAlmostEqual(ie.get_average_voltage(), 1.84143141, 3)

    def test_voltage_pair(self):
        vpair = self.ie_LTO[0]
        self.assertAlmostEqual(vpair.voltage, 2.78583901)
        self.assertAlmostEqual(vpair.mAh, 13400.7411749, 2)
        self.assertAlmostEqual(vpair.mass_charge, 79.8658)
        self.assertAlmostEqual(vpair.mass_discharge, 83.3363)
        self.assertAlmostEqual(vpair.vol_charge, 37.553684467)
        self.assertAlmostEqual(vpair.vol_discharge, 37.917719932)
        self.assertAlmostEqual(vpair.frac_charge, 0.0)
        self.assertAlmostEqual(vpair.frac_discharge, 0.14285714285714285)
示例#5
0
                    )
                )
                self.logger.debug(
                    f"Grouped entries in sandbox {', '.join([en.name for en in group_sbx])}"
                )
=======
                group_sbx = list(filter(lambda ent : (isbx in ent.data['_sbxn']) or (ent.data['_sbxn']==['core']), group))
                self.logger.debug(f"Grouped entries in sandbox {isbx} -- {', '.join([en.name for en in group_sbx])}")
>>>>>>> master
                result = InsertionElectrode(group_sbx, self.working_ion_entry)

                spacegroup = SpacegroupAnalyzer(
                    result.get_stable_entries(charge_to_discharge=True)[0].structure
                )

                d = result.as_dict_summary()

                # d['stable_material_ids'] = [entry.entry_id
                #                        for entry in result.get_stable_entries()]
                # d['unstable_material_ids'] = [entry.entry_id
                #                             for entry in result.get_unstable_entries()]
                # d['stability_data'] = {entry.entry_id : entry.data['decomposition_energy']
                #                               for entry in result.get_all_entries()}
                # d['muO2_data'] = {entry.entry_id : entry.data['muO2']
                #                        for entry in result.get_all_entries()}

                # sort the ids based on value
                ids = [entry.entry_id for entry in result.get_all_entries()]
                lowest_id = sorted(ids, key=lambda x: x.split("-")[-1])[0]
                d["spacegroup"] = {
                    k: spacegroup._space_group_data[k] for k in sg_fields