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
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
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