def __init__(self, composition, energy, correction=0.0, parameters=None, data=None, entry_id=None, attribute=None): """ Initializes a ComputedEntry. Args: composition (Composition): Composition of the entry. For flexibility, this can take the form of all the typical input taken by a Composition, including a {symbol: amt} dict, a string formula, and others. energy (float): Energy of the entry. Usually the final calculated energy from VASP or other electronic structure codes. correction (float): A correction to be applied to the energy. This is used to modify the energy for certain analyses. Defaults to 0.0. parameters (dict): An optional dict of parameters associated with the entry. Defaults to None. data (dict): An optional dict of any additional data associated with the entry. Defaults to None. entry_id (obj): An optional id to uniquely identify the entry. attribute: Optional attribute of the entry. This can be used to specify that the entry is a newly found compound, or to specify a particular label for the entry, or else ... Used for further analysis and plotting purposes. An attribute can be anything but must be MSONable. """ comp = Composition(composition) PDEntry.__init__(self, comp, energy, attribute=attribute) self.correction = correction self.parameters = parameters if parameters else {} self.data = data if data else {} self.entry_id = entry_id self._attribute = attribute
def __init__(self, composition, energy, correction=0.0, parameters=None, data=None, entry_id=None, attribute=None): """ Args: composition: Composition of the entry. For flexibility, this can take the form of all the typical input taken by a Composition, including a {symbol: amt} dict, a string formula, and others. energy: Energy of the entry. Usually the final calculated energy from VASP or other electronic structure codes. correction: A correction to be applied to the energy. This is used to modify the energy for certain analyses. Defaults to 0.0. parameters: An optional dict of parameters associated with the entry. Defaults to None. data: An optional dict of any additional data associated with the entry. Defaults to None. entry_id: An optional id to uniquely identify the entry. attribute: Optional attribute of the entry. This can be used to specify that the entry is a newly found compound, or to specify a particular label for the entry, or else ... Used for further analysis and plotting purposes. An attribute can be anything but must be MSONable. """ comp = Composition(composition) PDEntry.__init__(self, comp, energy, attribute=attribute) self.correction = correction self.parameters = parameters if parameters else {} self.data = data if data else {} self.entry_id = entry_id self._attribute = attribute
def __init__(self, composition, thermodata, temperature=298): """ Args: composition: Composition of the entry. For flexibility, this can take the form of all the typical input taken by a Composition, including a {symbol: amt} dict, a string formula, and others. thermodata: A sequence of ThermoData associated with the entry. temperature: A temperature for the entry in Kelvin. Defaults to 298K. """ comp = Composition(composition) self._thermodata = thermodata found = False enthalpy = float("inf") for data in self._thermodata: if data.type == "fH" and data.value < enthalpy and \ (data.phaseinfo != "gas" and data.phaseinfo != "liquid"): enthalpy = data.value found = True if not found: raise ValueError("List of Thermodata does not contain enthalpy " "values.") self.temperature = temperature PDEntry.__init__(self, comp, enthalpy)
def step2(**kwargs): """ post process: get energies from the jobs in the previous step and generate the phase diagram """ chkfile = kwargs['checkpoint_files'][0] all_jobs = jobs_from_file(chkfile) entries = [] # add endpoint data Al = Composition("Al1O0") energy_al = -3.36 O = Composition("Al0O1") energy_o = -2.58 entries.append(PDEntry(Al, energy_al)) entries.append(PDEntry(O, energy_o)) # get data and create entries for job in all_jobs: comp = job.vis.mplmp.structure.composition energy = job.final_energy entries.append(PDEntry(comp, energy)) pd = PhaseDiagram(entries) plotter = PDPlotter(pd, show_unstable=True) plotter.write_image('Al_O_phasediagram.jpg') return None
def setUp(self): entrylist = list() weights = list() comp = Composition("Mn2O3") entry = PDEntry(comp, 49) entrylist.append(PourbaixEntry(entry)) weights.append(1.0) comp = Ion.from_formula("MnO4[-]") entry = IonEntry(comp, 25) entrylist.append(PourbaixEntry(entry)) weights.append(0.25) comp = Composition("Fe2O3") entry = PDEntry(comp, 50) entrylist.append(PourbaixEntry(entry)) weights.append(0.5) comp = Ion.from_formula("Fe[2+]") entry = IonEntry(comp, 15) entrylist.append(PourbaixEntry(entry)) weights.append(2.5) comp = Ion.from_formula("Fe[3+]") entry = IonEntry(comp, 20) entrylist.append(PourbaixEntry(entry)) weights.append(1.5) self.weights = weights self.entrylist = entrylist self.multientry = MultiEntry(entrylist, weights)
def __init__(self, composition, energy, correction=0.0, parameters=None, data=None, entry_id=None): """ Args: composition: Composition of the entry. For flexibility, this can take the form of all the typical input taken by a Composition, including a {symbol: amt} dict, a string formula, and others. energy: Energy of the entry. Usually the final calculated energy from VASP or other electronic structure codes. correction: A correction to be applied to the energy. This is used to modify the energy for certain analyses. Defaults to 0.0. parameters: An optional dict of parameters associated with the entry. Defaults to None. data: An optional dict of any additional data associated with the entry. Defaults to None. entry_id: An optional id to uniquely identify the entry. """ comp = Composition(composition) PDEntry.__init__(self, comp, energy) self.correction = correction self.parameters = parameters if parameters else {} self.data = data if data else {} self.entry_id = entry_id
def test_1d_pd(self): entry = PDEntry('H', 0) pd = PhaseDiagram([entry]) pda = PDAnalyzer(pd) decomp, e = pda.get_decomp_and_e_above_hull(PDEntry('H', 1)) self.assertAlmostEqual(e, 1) self.assertAlmostEqual(decomp[entry], 1.0)
def __init__(self, composition, thermodata, temperature=298): comp = Composition(composition) self._thermodata = thermodata found = False enthalpy = float("inf") for data in self._thermodata: if data.type == "fH" and data.value < enthalpy and \ (data.phaseinfo != "gas" and data.phaseinfo != "liquid"): enthalpy = data.value found = True if not found: raise ValueError("List of Thermodata does not contain enthalpy " "values.") self.temperature = temperature PDEntry.__init__(self, comp, enthalpy)
def test_read_write_csv(self): Zn_solids = ["Zn", "ZnO", "ZnO2"] sol_g = [0.0, -3.338, -1.315] Zn_ions = ["Zn[2+]", "ZnOH[+]", "HZnO2[-]", "ZnO2[2-]", "ZnO"] liq_g = [-1.527, -3.415, -4.812, -4.036, -2.921] liq_conc = [1e-6, 1e-6, 1e-6, 1e-6, 1e-6] solid_entry = list() for sol in Zn_solids: comp = Composition(sol) delg = sol_g[Zn_solids.index(sol)] solid_entry.append(PourbaixEntry(PDEntry(comp, delg))) ion_entry = list() for ion in Zn_ions: comp_ion = Ion.from_formula(ion) delg = liq_g[Zn_ions.index(ion)] conc = liq_conc[Zn_ions.index(ion)] PoE = PourbaixEntry(IonEntry(comp_ion, delg)) PoE.conc = conc ion_entry.append(PoE) entries = solid_entry + ion_entry PourbaixEntryIO.to_csv("pourbaix_test_entries.csv", entries) (elements, entries) = PourbaixEntryIO.from_csv("pourbaix_test_entries.csv") self.assertEqual( elements, [Element('Zn'), Element('H'), Element('O')], "Wrong elements!") self.assertEqual(len(entries), 8, "Wrong number of entries!") os.remove("pourbaix_test_entries.csv")
def pd_plot(system='Ni-Nb'): object_file = pickle.load(open('form_en_gbsave_v25h', "rb")) output = [] l = system.split('-') comb = [] for i in range(len(l)): comb += itertools.combinations(l, i + 1) comb_list = [list(t) for t in comb] # comb_list=['Zn','O','Zn-O'] with MPRester("") as m: for i in comb_list: dd = '-'.join(i) print dd data = m.get_data(dd) for d in data: x = {} x['material_id'] = str(d['material_id']) structure = m.get_structure_by_material_id(x['material_id']) X = get_comp_descp(struct=structure) print "X", X pred = object_file.predict(X) print structure.composition.reduced_formula, pred[0], d[ 'formation_energy_per_atom'], str(d['material_id']) output.append( PDEntry(Composition(structure.composition), float(pred[0]))) pd = PhaseDiagram(output) print output plotter = PDPlotter(pd, show_unstable=True) name = str(system) + str('_phasediagram.png') plotter.write_image(name, image_format="png")
def test_to_from_dict(self): d = self.entry.as_dict() gpd = self.gpentry.as_dict() entry = PDEntry.from_dict(d) self.assertEqual(entry.name, "LiFeO2", "Wrong name!") self.assertEqual(entry.energy_per_atom, 53.0 / 4) gpentry = GrandPotPDEntry.from_dict(gpd) self.assertEqual(gpentry.name, "LiFeO2", "Wrong name!") self.assertEqual(gpentry.energy_per_atom, 50.0 / 2) d_anon = d.copy() del d_anon["name"] try: entry = PDEntry.from_dict(d_anon) except KeyError: self.fail("Should not need to supply name!")
def setUp(self): comp = Composition("LiFeO2") entry = PDEntry(comp, 53) self.transformed_entry = TransformedPDEntry( { DummySpecie('Xa'): 1, DummySpecie("Xb"): 1 }, entry)
def setUp(self): comp = Composition("Mn2O3") self.solentry = PDEntry(comp, 49) ion = Ion.from_formula("MnO4-") self.ionentry = IonEntry(ion, 25) self.PxIon = PourbaixEntry(self.ionentry) self.PxSol = PourbaixEntry(self.solentry) self.PxIon.conc = 1e-4
def test_to_from_dict(self): d = self.entry.as_dict() gpd = self.gpentry.as_dict() entry = PDEntry.from_dict(d) self.assertEqual(entry.name, 'LiFeO2', "Wrong name!") self.assertEqual(entry.energy_per_atom, 53.0 / 4) gpentry = GrandPotPDEntry.from_dict(gpd) self.assertEqual(gpentry.name, 'LiFeO2', "Wrong name!") self.assertEqual(gpentry.energy_per_atom, 50.0 / 2) d_anon = d.copy() del d_anon['name'] try: entry = PDEntry.from_dict(d_anon) except KeyError: self.fail("Should not need to supply name!")
def get_mu_range(mpid, ext_elts=[]): if 'hse' in mpid: mpid = mpid.split('_')[0] try: entry = m.get_entry_by_material_id(mpid) in_MP = True except: from high_throughput.defects.database import TasksOperater in_MP = False TO = TasksOperater() id_ = TO.groups['bulk'][mpid][0] rec = TO.collection.find_one({'_id':id_},['output']) stru_tmp =Structure.from_dict(rec['output']['crystal']) energy = rec['output']['final_energy'] entry = PDEntry(stru_tmp.composition, energy) elts = [i.symbol for i in entry.composition.elements] for i in ext_elts: elts.append(i) entries = m.get_entries_in_chemsys(elts) if not in_MP: entries.append(entry) for entry in entries: entry.correction = 0.0 pd=PhaseDiagram(entries) pda=PDAnalyzer(pd) chempots={} decompositions=pda.get_decomposition(entry.composition).keys() decomposition_inds=[pd.qhull_entries.index(entry) for entry in decompositions] facets_around=[] for facet in pd.facets: is_facet_around=True for ind in decomposition_inds: if ind not in facet: is_facet_around=False if is_facet_around==True: facets_around.append(facet) for facet in facets_around: s=[] for ind in facet: s.append(str(pd.qhull_entries[ind].name)) s.sort() chempots['-'.join(s)]=pda.get_facet_chempots(facet) chempots={i:{j.symbol:chempots[i][j] for j in chempots[i]} for i in chempots} return chempots
def test_to_from_dict(self): d = self.entry.as_dict() gpd = self.gpentry.as_dict() entry = PDEntry.from_dict(d) self.assertEqual(entry.name, 'LiFeO2', "Wrong name!") self.assertEqual(entry.energy_per_atom, 53.0 / 4) gpentry = GrandPotPDEntry.from_dict(gpd) self.assertEqual(gpentry.name, 'LiFeO2', "Wrong name!") self.assertEqual(gpentry.energy_per_atom, 50.0 / 2)
class PDEntryTest(unittest.TestCase): ''' Test all functions using a ficitious entry ''' def setUp(self): comp = Composition("LiFeO2") self.entry = PDEntry(comp, 53) self.gpentry = GrandPotPDEntry(self.entry, {Element('O'): 1.5}) def test_get_energy(self): self.assertEqual(self.entry.energy, 53, "Wrong energy!") self.assertEqual(self.gpentry.energy, 50, "Wrong energy!") def test_get_energy_per_atom(self): self.assertEqual(self.entry.energy_per_atom, 53.0 / 4, "Wrong energy per atom!") self.assertEqual(self.gpentry.energy_per_atom, 50.0 / 2, "Wrong energy per atom!") def test_get_name(self): self.assertEqual(self.entry.name, 'LiFeO2', "Wrong name!") self.assertEqual(self.gpentry.name, 'LiFeO2', "Wrong name!") def test_get_composition(self): comp = self.entry.composition expected_comp = Composition('LiFeO2') self.assertEqual(comp, expected_comp, "Wrong composition!") comp = self.gpentry.composition expected_comp = Composition("LiFe") self.assertEqual(comp, expected_comp, "Wrong composition!") def test_is_element(self): self.assertFalse(self.entry.is_element) self.assertFalse(self.gpentry.is_element) def test_to_from_dict(self): d = self.entry.as_dict() gpd = self.gpentry.as_dict() entry = PDEntry.from_dict(d) self.assertEqual(entry.name, 'LiFeO2', "Wrong name!") self.assertEqual(entry.energy_per_atom, 53.0 / 4) gpentry = GrandPotPDEntry.from_dict(gpd) self.assertEqual(gpentry.name, 'LiFeO2', "Wrong name!") self.assertEqual(gpentry.energy_per_atom, 50.0 / 2) d_anon = d.copy() del d_anon['name'] try: entry = PDEntry.from_dict(d_anon) except KeyError: self.fail("Should not need to supply name!") def test_str(self): self.assertIsNotNone(str(self.entry))
def test_planar_inputs(self): e1 = PDEntry('H', 0) e2 = PDEntry('HLiB', 0) e3 = PDEntry('He', 0) e4 = PDEntry('Li', 0) e5 = PDEntry('Be', 0) e6 = PDEntry('B', 0) e7 = PDEntry('HBe', 0) e8 = PDEntry('Rb', 0) pd = PhaseDiagram([e1, e2, e3, e4, e5, e6, e7, e8], map(Element, ['Rb', 'He', 'B', 'Be', 'Li', 'He', 'H']))
def from_dict(cls, d): """ Returns a PourbaixEntry by reading in an Ion """ entry_type = d["entry type"] if entry_type == "Ion": entry = IonEntry.from_dict(d["entry"]) else: entry = PDEntry.from_dict(d["entry"]) correction = d["correction"] entry_id = d["entry_id"] return PourbaixEntry(entry, correction, entry_id)
def __init__(self, entries, working_ion_entry): """ Create a new InsertionElectrode. Args: entries: A list of ComputedStructureEntries (or subclasses) representing the different topotactic states of the battery, e.g. TiO2 and LiTiO2. working_ion_entry: A single ComputedEntry or PDEntry representing the element that carries charge across the battery, e.g. Li. """ self._entries = entries self._working_ion = working_ion_entry.composition.elements[0] self._working_ion_entry = working_ion_entry #Prepare to make phase diagram: determine elements and set their energy #to be very high elements = set() map(elements.update, [entry.composition.elements for entry in entries]) #Set an artificial energy for each element for convex hull generation element_energy = max([entry.energy_per_atom for entry in entries]) + 10 pdentries = [] pdentries.extend(entries) pdentries.extend( [PDEntry(Composition({el: 1}), element_energy) for el in elements]) #Make phase diagram to determine which entries are stable vs. unstable pd = PhaseDiagram(pdentries) lifrac = lambda e: e.composition.get_atomic_fraction(self._working_ion) #stable entries ordered by amount of Li asc self._stable_entries = tuple( sorted([e for e in pd.stable_entries if e in entries], key=lifrac)) #unstable entries ordered by amount of Li asc self._unstable_entries = tuple( sorted([e for e in pd.unstable_entries if e in entries], key=lifrac)) #create voltage pairs self._vpairs = tuple([ InsertionVoltagePair(self._stable_entries[i], self._stable_entries[i + 1], working_ion_entry) for i in range(len(self._stable_entries) - 1) ])
def setUp(self): (elements, entries) = PDEntryIO.from_csv( os.path.join(module_dir, "pdentries_test.csv")) self.pd = PhaseDiagram(entries) self.plotter = PDPlotter(self.pd, show_unstable=True) entrieslio = [ e for e in entries if len(e.composition) < 3 and ("Fe" not in e.composition) ] self.pd_formation = PhaseDiagram(entrieslio) self.plotter_formation = PDPlotter(self.pd_formation, show_unstable=True) entries.append(PDEntry("C", 0)) self.pd3d = PhaseDiagram(entries) self.plotter3d = PDPlotter(self.pd3d, show_unstable=True)
def test_planar_inputs(self): e1 = PDEntry('H', 0) e2 = PDEntry('He', 0) e3 = PDEntry('Li', 0) e4 = PDEntry('Be', 0) e5 = PDEntry('B', 0) e6 = PDEntry('Rb', 0) pd = PhaseDiagram([e1, e2, e3, e4, e5, e6], map(Element, ['Rb', 'He', 'B', 'Be', 'Li', 'H'])) self.assertEqual(len(pd.facets), 1)
def get_phase_diagram_plot(self): """ Returns a phase diagram plot, as a matplotlib plot object. """ # set the font to Times, rendered with Latex plt.rc('font', **{'family': 'serif', 'serif': ['Times']}) plt.rc('text', usetex=True) # parse the composition space endpoints endpoints_line = self.lines[0].split() endpoints = [] for word in endpoints_line[::-1]: if word == 'endpoints:': break else: endpoints.append(Composition(word)) if len(endpoints) < 2: print('There must be at least 2 endpoint compositions to make a ' 'phase diagram.') quit() # parse the compositions and total energies of all the structures compositions = [] total_energies = [] for i in range(4, len(self.lines)): line = self.lines[i].split() compositions.append(Composition(line[1])) total_energies.append(float(line[2])) # make a list of PDEntries pdentries = [] for i in range(len(compositions)): pdentries.append(PDEntry(compositions[i], total_energies[i])) # make a CompoundPhaseDiagram compound_pd = CompoundPhaseDiagram(pdentries, endpoints) # make a PhaseDiagramPlotter pd_plotter = PDPlotter(compound_pd, show_unstable=100) return pd_plotter.get_plot(label_unstable=False)
def from_csv(filename): """ Imports PourbaixEntries from a csv. Args: filename - Filename to import from. Returns: List of Entries """ import csv reader = csv.reader(open(filename, "rb"), delimiter=",", quotechar="\"", quoting=csv.QUOTE_MINIMAL) entries = list() header_read = False for row in reader: if not header_read: elements = row[1:(len(row) - 4)] header_read = True else: name = row[0] energy = float(row[-4]) conc = float(row[-1]) comp = dict() for ind in range(1, len(row) - 4): if float(row[ind]) > 0: comp[Element(elements[ind - 1])] = float(row[ind]) phase_type = row[-3] if phase_type == "Ion": PoE = PourbaixEntry( IonEntry(Ion.from_formula(name), energy)) PoE.set_conc(conc) PoE.set_name(name) entries.append(PoE) else: entries.append( PourbaixEntry(PDEntry(Composition(comp), energy))) elements = [Element(el) for el in elements] return elements, entries
# creating array with energies from pbe enpbe = [] for y in file_energies_pbe.read().splitlines(): enpbe.append(float(y)) term_comp = [ Composition(names[7]), Composition(names[11]), Composition(names[32]) ] # creating entries from for the LDA phase diagram entries_lda = [] for i in range(len(names)): # entries_lda.append(PDEntry(names[i],enlda[i], names[i], "LDA")) entries_lda.append(PDEntry(names[i], enlda[i], " ", "LDA")) # creating the phase diagram for LDA pd_lda = PhaseDiagram(entries_lda) cpd_lda = CompoundPhaseDiagram(entries_lda, term_comp, normalize_terminal_compositions=True) a_lda = PDAnalyzer(pd_lda) # creating entries from for the PBE phase diagram entries_pbe = [] for i in range(len(names)): # entries_pbe.append(PDEntry(names[i],enpbe[i], names[i], "PBE")) entries_pbe.append(PDEntry(names[i], enpbe[i], " ", "PBE")) # creating the phase diagram for PBE
turn_knobs=turn_knobs, qadapter=qadapter, job_cmd=job_cmd, job_dir=job_dir, is_matrix=True, checkpoint_file=chkpt_file, cal_logger=logger) cal.setup() cal.run() checkpoint_files.append(chkpt_file) #plotter = PDPlotter(pd, show_unstable=True) print("ff=", ff) # return checkpoint_files all_jobs = jobs_from_file(chkpt_file) entries = [] for job in all_jobs: comp = job.vis.mplmp.structure.composition energy = job.final_energy entries.append(PDEntry(comp, energy)) try: pd = PhaseDiagram(entries) plotter = PDPlotter(pd, show_unstable=True) image_ff = str(ff) + str("_CLASS") + str(".jpg") plotter.write_image(image_ff) except: pass except: pass ## pass
def setUp(self): comp = Composition("LiFeO2") self.entry = PDEntry(comp, 53) self.gpentry = GrandPotPDEntry(self.entry, {Element('O'): 1.5})
def main(comp="La0.5Sr0.5MnO3", energy=-43.3610, ostart="", oend="", ostep=""): """Get energy above hull for a composition Args: comp <str>: Composition in string form energy <float>: Energy PER FORMULA UNIT of composition given (Leave the following arguments blank for a non-grand potential phase diagram.) ostart <float>: Starting oxygen chemical potential. oend <float>: Ending oxygen chemical potential. ostep <float>: Step for oxygen chemical potential Returns: Prints to screen """ #a = MPRester("<YOUR_MPREST_API_KEY_HERE>") a = MPRester("wfmUu5VSsDCvIrhz") mycomp = Composition(comp) print "Composition: ", mycomp myenergy = energy print "Energy: ", myenergy myPDEntry = PDEntry(mycomp, myenergy) elements = mycomp.elements ellist = map(str, elements) chemsys_entries = a.get_entries_in_chemsys(ellist) #For reference: other ways of getting entries #entries = a.mpquery(criteria={'elements':{'$in':['La','Mn'],'$all':['O']},'nelements':3}) #entries = a.mpquery(criteria={'elements':{'$in':['La','Mn','O'],'$all':['O']}},properties=['pretty_formula']) #entries = a.get_entries_in_chemsys(['La', 'Mn', 'O', 'Sr']) if ostart == "": #Regular phase diagram entries = list(chemsys_entries) entries.append(myPDEntry) pd = PhaseDiagram(entries) #plotter = PDPlotter(gppd) #plotter.show() ppda = PDAnalyzer(pd) eabove = ppda.get_decomp_and_e_above_hull(myPDEntry) print "Energy above hull: ", eabove[1] print "Decomposition: ", eabove[0] return eabove else: #Grand potential phase diagram orange = np.arange( ostart, oend + ostep, ostep) #add ostep because otherwise the range ends before oend for o_chem_pot in orange: entries = list(chemsys_entries) myGrandPDEntry = GrandPotPDEntry( myPDEntry, {Element('O'): float(o_chem_pot) }) #need grand pot pd entry for GPPD entries.append(myGrandPDEntry) gppd = GrandPotentialPhaseDiagram( entries, {Element('O'): float(o_chem_pot)}) gppda = PDAnalyzer(gppd) geabove = gppda.get_decomp_and_e_above_hull(myGrandPDEntry, True) print "******** Decomposition for mu_O = %s eV ********" % o_chem_pot print "%30s%1.4f" % ("mu_O: ", o_chem_pot) print "%30s%1.4f" % ("Energy above hull (eV): ", geabove[1]) decomp = geabove[0] #print "Decomp: ", decomp print "%30s" % "Decomposition: " for dkey in decomp.keys(): print "%30s:%1.4f" % (dkey.composition, decomp[dkey]) return
def get_entries_from_json(key=None, value=None, out=None, ff=None, json_f=None, PD=False): output = [[]] file = json_f with open(file, 'r') as f: data = json.load(f) if key == 'search': output = [] try: old = value.split('-') el_list = sorted(old) value = ('-'.join([item for item in el_list])) except: pass for d in data: x = {} options = [ 'mpid', 'ehull', 'Bv', 'Gv', 'totenergy', 'energy', 'case-number', 'elastic_matrix', 'forcefield', 'composition' ] x[key] = str(d[key]) x['mpid'] = str(d['mpid']) x['ehull'] = str(d['ehull']) x['Bv'] = str(d['Bv']) x['Gv'] = str(d['Gv']) x['totenergy'] = str(d['totenergy']) x['energy'] = str(d['energy']) x['case-number'] = str(d['case-number']) x['elastic_matrix'] = str(d['elastic_matrix']) x['forcefield'] = str(d['forcefield']) x['composition'] = str(d['composition']) #if key != 'search': if x[key] == value and x['forcefield'] == ff and PD == False: output = x[out] if x[key] == value and ff == None and PD == False: print(x[out], x['forcefield']) if x[key] == value and x['forcefield'] == ff and PD == True: output.append( PDEntry(Composition(x['composition']), float(x['totenergy']))) if key == 'search' and len(value.split('-')) > 1 and PD == True: els = value.split('-') for el in els: if x[key] == el and x['forcefield'] == ff: output.append( PDEntry(Composition(x['composition']), float(x['totenergy']))) for el1 in els: for el2 in els: if x[key] == str(el1) + str('-') + str( el2) and x['forcefield'] == ff: output.append( PDEntry(Composition(x['composition']), float(x['totenergy']))) if x[key] == str(el2) + str('-') + str( el1) and x['forcefield'] == ff: output.append( PDEntry(Composition(x['composition']), float(x['totenergy']))) return output