Ejemplo n.º 1
0
    def _get_int_removals_helper(self, spec_amts_oxi, redox_el, redox_els,
                                 numa):
        """
        This is a helper method for get_removals_int_oxid!

        Args:
            spec_amts_oxi - a dict of species to their amounts in the structure
            redox_el - the element to oxidize or reduce
            redox_els - the full list of elements that might be oxidized or reduced
            numa - a running set of numbers of A ion at integer oxidation steps
        Returns:
            a set of numbers A; steps for for oxidizing oxid_el first, then the other oxid_els in this list
        """

        # If a given redox_el has multiple oxidation states present in the structure, we want
        # to oxidize the lowest state or reduce the highest state
        if self.working_ion_charge < 0:
            oxid_old = max(spec.oxi_state for spec in spec_amts_oxi
                           if spec.symbol == redox_el.symbol)
            oxid_new = math.ceil(oxid_old - 1)
            lowest_oxid = defaultdict(lambda: 2, {"Cu": 1})
            # if this is not a valid solution, break out of here and don't add anything to the list
            if oxid_new < min(
                    os for os in Element(redox_el.symbol).oxidation_states
                    if os >= lowest_oxid[redox_el.symbol]):
                return numa
        else:
            oxid_old = min(spec.oxi_state for spec in spec_amts_oxi
                           if spec.symbol == redox_el.symbol)
            oxid_new = math.floor(oxid_old + 1)
            # if this is not a valid solution, break out of here and don't add anything to the list
            if oxid_new > redox_el.max_oxidation_state:
                return numa
        # update the spec_amts_oxi map to reflect that the redox took place
        spec_old = Species(redox_el.symbol, oxid_old)
        spec_new = Species(redox_el.symbol, oxid_new)
        specamt = spec_amts_oxi[spec_old]
        spec_amts_oxi = {
            sp: amt
            for sp, amt in spec_amts_oxi.items() if sp != spec_old
        }
        spec_amts_oxi[spec_new] = specamt
        spec_amts_oxi = Composition(spec_amts_oxi)

        # determine the amount of ion A in the structure needed for charge balance and add it to the list
        oxi_noA = sum(spec.oxi_state * spec_amts_oxi[spec]
                      for spec in spec_amts_oxi
                      if spec.symbol not in self.working_ion.symbol)
        a = max(0, -oxi_noA / self.working_ion_charge)
        numa = numa.union({a})

        # recursively try the other oxidation states
        if a == 0:
            return numa
        for red in redox_els:
            numa = numa.union(
                self._get_int_removals_helper(spec_amts_oxi.copy(), red,
                                              redox_els, numa))
        return numa
Ejemplo n.º 2
0
    def _get_int_removals_helper(self, spec_amts_oxi, oxid_el, oxid_els, numa):
        """
        This is a helper method for get_removals_int_oxid!

        Args:
            spec_amts_oxi - a dict of species to their amounts in the structure
            oxid_el - the element to oxidize
            oxid_els - the full list of elements that might be oxidized
            numa - a running set of numbers of A cation at integer oxidation steps
        Returns:
            a set of numbers A; steps for for oxidizing oxid_el first, then the other oxid_els in this list
        """

        # If Mn is the oxid_el, we have a mixture of Mn2+, Mn3+, determine the minimum oxidation state for Mn
        #this is the state we want to oxidize!
        oxid_old = min([
            spec.oxi_state for spec in spec_amts_oxi
            if spec.symbol == oxid_el.symbol
        ])
        oxid_new = math.floor(oxid_old + 1)
        #if this is not a valid solution, break out of here and don't add anything to the list
        if oxid_new > oxid_el.max_oxidation_state:
            return numa

        #update the spec_amts_oxi map to reflect that the oxidation took place
        spec_old = Specie(oxid_el.symbol, oxid_old)
        spec_new = Specie(oxid_el.symbol, oxid_new)
        specamt = spec_amts_oxi[spec_old]
        spec_amts_oxi = {
            sp: amt
            for sp, amt in spec_amts_oxi.items() if sp != spec_old
        }
        spec_amts_oxi[spec_new] = specamt
        spec_amts_oxi = Composition(spec_amts_oxi)

        #determine the amount of cation A in the structure needed for charge balance and add it to the list
        oxi_noA = sum([
            spec.oxi_state * spec_amts_oxi[spec] for spec in spec_amts_oxi
            if spec.symbol not in self.cation.symbol
        ])
        a = max(0, -oxi_noA / self.cation_charge)
        numa = numa.union({a})

        #recursively try the other oxidation states
        if a == 0:
            return numa
        else:
            for oxid_el in oxid_els:
                numa = numa.union(
                    self._get_int_removals_helper(spec_amts_oxi.copy(),
                                                  oxid_el, oxid_els, numa))
            return numa
Ejemplo n.º 3
0
    def _get_int_removals_helper(self, spec_amts_oxi, oxid_el, oxid_els, numa):
        """
        This is a helper method for get_removals_int_oxid!

        Args:
            spec_amts_oxi - a dict of species to their amounts in the structure
            oxid_el - the element to oxidize
            oxid_els - the full list of elements that might be oxidized
            numa - a running set of numbers of A cation at integer oxidation steps
        Returns:
            a set of numbers A; steps for for oxidizing oxid_el first, then the other oxid_els in this list
        """

        # If Mn is the oxid_el, we have a mixture of Mn2+, Mn3+, determine the minimum oxidation state for Mn
        #this is the state we want to oxidize!
        oxid_old = min([spec.oxi_state for spec in spec_amts_oxi if spec.symbol == oxid_el.symbol])
        oxid_new = math.floor(oxid_old + 1)
        #if this is not a valid solution, break out of here and don't add anything to the list
        if oxid_new > oxid_el.max_oxidation_state:
            return numa

        #update the spec_amts_oxi map to reflect that the oxidation took place
        spec_old = Specie(oxid_el.symbol, oxid_old)
        spec_new = Specie(oxid_el.symbol, oxid_new)
        specamt = spec_amts_oxi[spec_old]
        spec_amts_oxi = {sp: amt for sp, amt in spec_amts_oxi.items() if sp != spec_old}
        spec_amts_oxi[spec_new] = specamt
        spec_amts_oxi = Composition(spec_amts_oxi)

        #determine the amount of cation A in the structure needed for charge balance and add it to the list
        oxi_noA = sum([spec.oxi_state * spec_amts_oxi[spec] for spec in spec_amts_oxi if
                       spec.symbol not in self.cation.symbol])
        a = max(0, -oxi_noA / self.cation_charge)
        numa = numa.union({a})

        #recursively try the other oxidation states
        if a == 0:
            return numa
        else:
            for oxid_el in oxid_els:
                numa = numa.union(
                    self._get_int_removals_helper(spec_amts_oxi.copy(), oxid_el, oxid_els, numa))
            return numa