示例#1
0
    def test_negative_compositions(self):
        self.assertEqual(Composition("Li-1(PO-1)4", allow_negative=True).formula, "Li-1 P4 O-4")
        self.assertEqual(Composition("Li-1(PO-1)4", allow_negative=True).reduced_formula, "Li-1(PO-1)4")
        self.assertEqual(
            Composition("Li-2Mg4", allow_negative=True).reduced_composition, Composition("Li-1Mg2", allow_negative=True)
        )
        self.assertEqual(
            Composition("Li-2.5Mg4", allow_negative=True).reduced_composition,
            Composition("Li-2.5Mg4", allow_negative=True),
        )

        # test math
        c1 = Composition("LiCl", allow_negative=True)
        c2 = Composition("Li")
        self.assertEqual(c1 - 2 * c2, Composition({"Li": -1, "Cl": 1}, allow_negative=True))
        self.assertEqual((c1 + c2).allow_negative, True)
        self.assertEqual(c1 / -1, Composition("Li-1Cl-1", allow_negative=True))

        # test num_atoms
        c1 = Composition("Mg-1Li", allow_negative=True)
        self.assertEqual(c1.num_atoms, 2)
        self.assertEqual(c1.get_atomic_fraction("Mg"), 0.5)
        self.assertEqual(c1.get_atomic_fraction("Li"), 0.5)
        self.assertEqual(c1.fractional_composition, Composition("Mg-0.5Li0.5", allow_negative=True))

        # test copy
        self.assertEqual(c1.copy(), c1)

        # test species
        c1 = Composition({"Mg": 1, "Mg2+": -1}, allow_negative=True)
        self.assertEqual(c1.num_atoms, 2)
        self.assertEqual(c1.element_composition, Composition())
        self.assertEqual(c1.average_electroneg, 1.31)
示例#2
0
    def test_negative_compositions(self):
        self.assertEqual(Composition('Li-1(PO-1)4', allow_negative=True).formula,
                         'Li-1 P4 O-4')
        self.assertEqual(Composition('Li-1(PO-1)4', allow_negative=True).reduced_formula,
                         'Li-1(PO-1)4')
        self.assertEqual(Composition('Li-2Mg4', allow_negative=True).reduced_composition,
                         Composition('Li-1Mg2', allow_negative=True))
        self.assertEqual(Composition('Li-2.5Mg4', allow_negative=True).reduced_composition,
                         Composition('Li-2.5Mg4', allow_negative=True))

        #test math
        c1 = Composition('LiCl', allow_negative=True)
        c2 = Composition('Li')
        self.assertEqual(c1 - 2 * c2, Composition({'Li': -1, 'Cl': 1},
                                                  allow_negative=True))
        self.assertEqual((c1 + c2).allow_negative, True)
        self.assertEqual(c1 / -1, Composition('Li-1Cl-1', allow_negative=True))

        #test num_atoms
        c1 = Composition('Mg-1Li', allow_negative=True)
        self.assertEqual(c1.num_atoms, 2)
        self.assertEqual(c1.get_atomic_fraction('Mg'), 0.5)
        self.assertEqual(c1.get_atomic_fraction('Li'), 0.5)
        self.assertEqual(c1.fractional_composition,
                         Composition('Mg-0.5Li0.5', allow_negative=True))

        #test copy
        self.assertEqual(c1.copy(), c1)

        #test species
        c1 = Composition({'Mg':1, 'Mg2+':-1}, allow_negative=True)
        self.assertEqual(c1.num_atoms, 2)
        self.assertEqual(c1.element_composition, Composition())
        self.assertEqual(c1.average_electroneg, 1.31)
		def parse_sites(row):
			comp = Composition(row)
			# get elements in the order of the compound // pymatgen's comp.formula gives elements sorted by electronegativity,
			# we don't want that.  We want to preserve A(A')B(B')O3 order
			elements = [''.join([i for i in elem if not i.isdigit()]).replace(".", "") for elem in comp.formula.split()]	
			indices = {e: row.find(e) for e in elements}
			A1, A2, B1, B2 = '_', '_', '_', '_'
			A1_frac, A2_frac, B1_frac, B2_frac, O_frac = 0, 0, 0, 0, 0
			if (len(row.split("(")[0])==0 or len(row.split("(")[0])>8):	# type =1   ### value '8' is hard coded and it works. But check
				A1, A2, B1, O = sorted(elements, key=indices.get)
				elem_fracs = [comp.get_atomic_fraction(Element(i))*comp.num_atoms for i in [A1, A2, B1, O]]
				# now formulate A(A')B(B')O3 format
				A1_frac, A2_frac, B1_frac, O_frac = [round(i*3.0/elem_fracs[-1], 3) for i in elem_fracs]
			else:	# type = 2
				A1, B1, B2, O = sorted(elements, key=indices.get)
				elem_fracs = [comp.get_atomic_fraction(Element(i))*comp.num_atoms for i in [A1, B1, B2, O]]
				A1_frac, B1_frac, B2_frac, O_frac = [round(i*3.0/elem_fracs[-1], 3) for i in elem_fracs]
				
			return A1, A1_frac, A2, A2_frac, B1, B1_frac, B2, B2_frac, O, O_frac
示例#4
0
    def test_negative_compositions(self):
        self.assertEqual(
            Composition("Li-1(PO-1)4", allow_negative=True).formula,
            "Li-1 P4 O-4")
        self.assertEqual(
            Composition("Li-1(PO-1)4", allow_negative=True).reduced_formula,
            "Li-1(PO-1)4",
        )
        self.assertEqual(
            Composition("Li-2Mg4", allow_negative=True).reduced_composition,
            Composition("Li-1Mg2", allow_negative=True),
        )
        self.assertEqual(
            Composition("Li-2.5Mg4", allow_negative=True).reduced_composition,
            Composition("Li-2.5Mg4", allow_negative=True),
        )

        # test math
        c1 = Composition("LiCl", allow_negative=True)
        c2 = Composition("Li")
        self.assertEqual(c1 - 2 * c2,
                         Composition({
                             "Li": -1,
                             "Cl": 1
                         }, allow_negative=True))
        self.assertEqual((c1 + c2).allow_negative, True)
        self.assertEqual(c1 / -1, Composition("Li-1Cl-1", allow_negative=True))

        # test num_atoms
        c1 = Composition("Mg-1Li", allow_negative=True)
        self.assertEqual(c1.num_atoms, 2)
        self.assertEqual(c1.get_atomic_fraction("Mg"), 0.5)
        self.assertEqual(c1.get_atomic_fraction("Li"), 0.5)
        self.assertEqual(c1.fractional_composition,
                         Composition("Mg-0.5Li0.5", allow_negative=True))

        # test copy
        self.assertEqual(c1.copy(), c1)

        # test species
        c1 = Composition({"Mg": 1, "Mg2+": -1}, allow_negative=True)
        self.assertEqual(c1.num_atoms, 2)
        self.assertEqual(c1.element_composition, Composition())
        self.assertEqual(c1.average_electroneg, 1.31)
示例#5
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)
示例#6
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,
        )
示例#7
0
def predict_k_g_list_of_entries(entries):
    """
    Predict bulk (K) and shear (G) moduli from a list of entries in the same
    format as retrieved from the Materials Project API.
    """

    lvpa_list = []
    cepa_list = []
    rowH1A_list = []
    rowHn3A_list = []
    xH4A_list = []
    xHn4A_list = []
    matid_list = []
    k_list = []
    g_list = []
    caveats_list = []
    aiab_problem_list = []

    # TODO: figure out if closing the query engine (using 'with' ctx mgr) is an issue
    # If it is a problem then try manually doing a session.close() for MPRester, but ignore for qe

    for entry in entries:

        caveats_str = ''
        aiab_flag = False
        f_block_flag = False
        weight_list = []
        energy_list = []
        row_list = []
        x_list = []

        # Construct per-element lists for this material
        composition = Composition(str(entry["pretty_formula"]))
        for element_key, amount in composition.get_el_amt_dict().items():
            element = Element(element_key)
            weight_list.append(composition.get_atomic_fraction(element))
            aiab_energy = get_element_aiab_energy(
                element_key)  # aiab = atom-in-a-box
            if aiab_energy is None:
                aiab_flag = True
                break
            energy_list.append(aiab_energy)
            if element.block == 'f':
                f_block_flag = True
            row_list.append(element.row)
            x_list.append(element.X)

        # On error, add material to aiab_problem_list and continue with next material
        if aiab_flag:
            aiab_problem_list.append(str(entry["material_id"]))
            continue

        # Check caveats
        if bool(entry["is_hubbard"]):
            if len(caveats_str) > 0: caveats_str += " "
            caveats_str += CAVEAT_HUBBARD
        if f_block_flag:
            if len(caveats_str) > 0: caveats_str += " "
            caveats_str += CAVEAT_F_BLOCK

        # Calculate intermediate weighted averages (WA) for this material
        ewa = np.average(energy_list,
                         weights=weight_list)  # atom-in-a-box energy WA

        print(str(entry["material_id"]))

        # Append descriptors for this material to descriptor lists
        lvpa_list.append(
            math.log10(float(entry["volume"]) / float(entry["nsites"])))
        cepa_list.append(float(entry["energy_per_atom"]) - ewa)
        rowH1A_list.append(holder_mean(row_list, 1.0, weights=weight_list))
        rowHn3A_list.append(holder_mean(row_list, -3.0, weights=weight_list))
        xH4A_list.append(holder_mean(x_list, 4.0, weights=weight_list))
        xHn4A_list.append(holder_mean(x_list, -4.0, weights=weight_list))
        matid_list.append(str(entry["material_id"]))
        caveats_list.append(caveats_str)

    # Check that at least one valid material was provided
    num_predictions = len(matid_list)
    if num_predictions > 0:
        # Construct descriptor arrays
        if (len(lvpa_list) != num_predictions
                or len(cepa_list) != num_predictions
                or len(rowH1A_list) != num_predictions
                or len(rowHn3A_list) != num_predictions
                or len(xH4A_list) != num_predictions
                or len(xHn4A_list) != num_predictions):
            return (None, None, None, None)
        k_descriptors = np.ascontiguousarray(
            [lvpa_list, rowH1A_list, cepa_list, xHn4A_list], dtype=float)
        g_descriptors = np.ascontiguousarray(
            [cepa_list, lvpa_list, rowHn3A_list, xH4A_list], dtype=float)

        # Allocate prediction arrays
        k_predictions = np.empty(num_predictions)
        g_predictions = np.empty(num_predictions)

        # Make predictions
        k_filename = os.path.join(os.path.dirname(__file__), DATAFILE_K)
        g_filename = os.path.join(os.path.dirname(__file__), DATAFILE_G)
        gbml.core.predict(k_filename, num_predictions, k_descriptors,
                          k_predictions)
        gbml.core.predict(g_filename, num_predictions, g_descriptors,
                          g_predictions)

        k_list = np.power(10.0, k_predictions).tolist()
        g_list = np.power(10.0, g_predictions).tolist()

    # Append aiab problem cases
    for entry in aiab_problem_list:
        matid_list.append(entry)
        k_list.append(None)
        g_list.append(None)
        caveats_list.append(CAVEAT_AIAB)

    if len(matid_list) == 0:
        return (None, None, None, None)
    else:
        return (matid_list, k_list, g_list, caveats_list)
示例#8
0
def predict_k_g_list_of_entries(entries):
    """
    Predict bulk (K) and shear (G) moduli from a list of entries in the same
    format as retrieved from the Materials Project API.
    """

    lvpa_list = []
    cepa_list = []
    rowH1A_list = []
    rowHn3A_list = []
    xH4A_list = []
    xHn4A_list = []
    matid_list = []
    k_list = []
    g_list = []
    caveats_list = []
    aiab_problem_list = []

    # TODO: figure out if closing the query engine (using 'with' ctx mgr) is an issue
    # If it is a problem then try manually doing a session.close() for MPRester, but ignore for qe

    for entry in entries:

        caveats_str = ''
        aiab_flag = False
        f_block_flag = False
        weight_list = []
        energy_list = []
        row_list = []
        x_list = []

        # Construct per-element lists for this material
        composition = Composition(str(entry["pretty_formula"]))
        for element_key, amount in composition.get_el_amt_dict().items():
            element = Element(element_key)
            weight_list.append(composition.get_atomic_fraction(element))
            aiab_energy = get_element_aiab_energy(element_key)  # aiab = atom-in-a-box
            if aiab_energy is None:
                aiab_flag = True
                break
            energy_list.append(aiab_energy)
            if element.block == 'f':
              f_block_flag = True
            row_list.append(element.row)
            x_list.append(element.X)

        # On error, add material to aiab_problem_list and continue with next material
        if aiab_flag:
            aiab_problem_list.append(str(entry["material_id"]))
            continue

        # Check caveats
        if bool(entry["is_hubbard"]):
            if len(caveats_str) > 0: caveats_str += " "
            caveats_str += CAVEAT_HUBBARD
        if f_block_flag:
            if len(caveats_str) > 0: caveats_str += " "
            caveats_str += CAVEAT_F_BLOCK

        # Calculate intermediate weighted averages (WA) for this material
        ewa = np.average(energy_list, weights=weight_list)      # atom-in-a-box energy WA

        print(str(entry["material_id"]))

        # Append descriptors for this material to descriptor lists
        lvpa_list.append(math.log10(float(entry["volume"]) / float(entry["nsites"])))
        cepa_list.append(float(entry["energy_per_atom"]) - ewa)
        rowH1A_list.append(holder_mean(row_list, 1.0, weights=weight_list))
        rowHn3A_list.append(holder_mean(row_list, -3.0, weights=weight_list))
        xH4A_list.append(holder_mean(x_list, 4.0, weights=weight_list))
        xHn4A_list.append(holder_mean(x_list, -4.0, weights=weight_list))
        matid_list.append(str(entry["material_id"]))
        caveats_list.append(caveats_str)

    # Check that at least one valid material was provided
    num_predictions = len(matid_list)
    if num_predictions > 0:
        # Construct descriptor arrays
        if (len(lvpa_list) != num_predictions or len(cepa_list) != num_predictions or
            len(rowH1A_list) != num_predictions or len(rowHn3A_list) != num_predictions or
            len(xH4A_list) != num_predictions or len(xHn4A_list) != num_predictions):
                return (None, None, None, None)
        k_descriptors = np.ascontiguousarray([lvpa_list, rowH1A_list, cepa_list, xHn4A_list],
            dtype=float)
        g_descriptors = np.ascontiguousarray([cepa_list, lvpa_list, rowHn3A_list, xH4A_list],
            dtype=float)

        # Allocate prediction arrays
        k_predictions = np.empty(num_predictions)
        g_predictions = np.empty(num_predictions)

        # Make predictions
        k_filename = os.path.join(os.path.dirname(__file__),DATAFILE_K)
        g_filename = os.path.join(os.path.dirname(__file__),DATAFILE_G)
        gbml.core.predict(k_filename, num_predictions, k_descriptors, k_predictions)
        gbml.core.predict(g_filename, num_predictions, g_descriptors, g_predictions)

        k_list = np.power(10.0, k_predictions).tolist()
        g_list = np.power(10.0, g_predictions).tolist()

    # Append aiab problem cases
    for entry in aiab_problem_list:
        matid_list.append(entry)
        k_list.append(None)
        g_list.append(None)
        caveats_list.append(CAVEAT_AIAB)

    if len(matid_list) == 0:
        return (None, None, None, None)
    else:
        return (matid_list, k_list, g_list, caveats_list)
示例#9
0
def predict_k_g_list(material_id_list, api_key=API_KEY, query_engine=None):
    """
    Predict bulk (K) and shear (G) moduli for a list of materials.
    :param material_id_list: list of material-ID strings
    :param api_key: The API key used by pymatgen.matproj.rest.MPRester to connect to Materials Project
    :param query_engine: (Optional) QueryEngine object used to query materials instead of MPRester
 
    :return: (matid_list, predicted_k_list, predicted_g_list, caveats_list)
    Note that len(matid_list) may be less than len(material_id_list),
    if any requested material-IDs are not found.
    """

    if len(material_id_list) == 0 or not isinstance(material_id_list, list):
        return (None, None, None, None
                )  # material_id_list not properly specified

    lvpa_list = []
    cepa_list = []
    rowH1A_list = []
    rowHn3A_list = []
    xH4A_list = []
    xHn4A_list = []
    matid_list = []
    k_list = []
    g_list = []
    caveats_list = []
    aiab_problem_list = []

    # TODO: figure out if closing the query engine (using 'with' ctx mgr) is an issue
    # If it is a problem then try manually doing a session.close() for MPRester, but ignore for qe

    mpr = _get_mp_query(api_key, query_engine)
    for entry in mpr.query(criteria={"task_id": {
            "$in": material_id_list
    }},
                           properties=[
                               "material_id", "pretty_formula", "nsites",
                               "volume", "energy_per_atom", "is_hubbard"
                           ]):

        caveats_str = ''
        aiab_flag = False
        f_block_flag = False
        weight_list = []
        energy_list = []
        row_list = []
        x_list = []

        # Construct per-element lists for this material
        composition = Composition(str(entry["pretty_formula"]))
        for element_key, amount in composition.get_el_amt_dict().iteritems():
            element = Element(element_key)
            weight_list.append(composition.get_atomic_fraction(element))
            aiab_energy = get_element_aiab_energy(
                element_key)  # aiab = atom-in-a-box
            if aiab_energy is None:
                aiab_flag = True
                break
            energy_list.append(aiab_energy)
            if element.block == 'f':
                f_block_flag = True
            row_list.append(element.row)
            x_list.append(element.X)

        # On error, add material to aiab_problem_list and continue with next material
        if aiab_flag:
            aiab_problem_list.append(str(entry["material_id"]))
            continue

        # Check caveats
        if bool(entry["is_hubbard"]):
            if len(caveats_str) > 0: caveats_str += " "
            caveats_str += CAVEAT_HUBBARD
        if f_block_flag:
            if len(caveats_str) > 0: caveats_str += " "
            caveats_str += CAVEAT_F_BLOCK

        # Calculate intermediate weighted averages (WA) for this material
        ewa = np.average(energy_list,
                         weights=weight_list)  # atom-in-a-box energy WA

        print str(entry["material_id"])

        # Append descriptors for this material to descriptor lists
        lvpa_list.append(
            math.log10(float(entry["volume"]) / float(entry["nsites"])))
        cepa_list.append(float(entry["energy_per_atom"]) - ewa)
        rowH1A_list.append(holder_mean(row_list, 1.0, weights=weight_list))
        rowHn3A_list.append(holder_mean(row_list, -3.0, weights=weight_list))
        xH4A_list.append(holder_mean(x_list, 4.0, weights=weight_list))
        xHn4A_list.append(holder_mean(x_list, -4.0, weights=weight_list))
        matid_list.append(str(entry["material_id"]))
        caveats_list.append(caveats_str)

    if isinstance(mpr, MPRester):
        mpr.session.close()

    # Check that at least one valid material was provided
    num_predictions = len(matid_list)
    if num_predictions > 0:
        # Construct descriptor arrays
        if (len(lvpa_list) != num_predictions
                or len(cepa_list) != num_predictions
                or len(rowH1A_list) != num_predictions
                or len(rowHn3A_list) != num_predictions
                or len(xH4A_list) != num_predictions
                or len(xHn4A_list) != num_predictions):
            return (None, None, None, None)
        k_descriptors = np.ascontiguousarray(
            [lvpa_list, rowH1A_list, cepa_list, xHn4A_list], dtype=float)
        g_descriptors = np.ascontiguousarray(
            [cepa_list, lvpa_list, rowHn3A_list, xH4A_list], dtype=float)

        # Allocate prediction arrays
        k_predictions = np.empty(num_predictions)
        g_predictions = np.empty(num_predictions)

        # Make predictions
        k_filename = os.path.join(os.path.dirname(__file__), DATAFILE_K)
        g_filename = os.path.join(os.path.dirname(__file__), DATAFILE_G)
        gbml.core.predict(k_filename, num_predictions, k_descriptors,
                          k_predictions)
        gbml.core.predict(g_filename, num_predictions, g_descriptors,
                          g_predictions)

        k_list = np.power(10.0, k_predictions).tolist()
        g_list = np.power(10.0, g_predictions).tolist()

    # Append aiab problem cases
    for entry in aiab_problem_list:
        matid_list.append(entry)
        k_list.append(None)
        g_list.append(None)
        caveats_list.append(CAVEAT_AIAB)

    if len(matid_list) == 0:
        return (None, None, None, None)
    else:
        return (matid_list, k_list, g_list, caveats_list)
示例#10
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)