Finds the element from "allowed elements" that (i) possesses the desired
    "oxidation state" and (ii) is closest in ionic radius to the target specie

    Args:
        target: (Specie) provides target ionic radius.
        oxidation_state: (float) codopant oxidation state.
        allowed_elements: ([str]) List of allowed elements. If None,
            all elements are tried.

    Returns:
        (Specie) with oxidation_state that has ionic radius closest to
        target.

def _find_codopant(target, oxidation_state, allowed_elements=None):
    """
    Finds the element from "allowed elements" that (i) possesses the desired
    "oxidation state" and (ii) is closest in ionic radius to the target specie

    Args:
        target: (Specie) provides target ionic radius.
        oxidation_state: (float) codopant oxidation state.
        allowed_elements: ([str]) List of allowed elements. If None,
            all elements are tried.

    Returns:
        (Specie) with oxidation_state that has ionic radius closest to
        target.
    """
    ref_radius = target.ionic_radius
    candidates = []
    symbols = allowed_elements or [el.symbol for el in Element]
    for sym in symbols:
        try:
            with warnings.catch_warnings():
                warnings.simplefilter("ignore")
                sp = Specie(sym, oxidation_state)
                r = sp.ionic_radius
                if r is not None:
                    candidates.append((r, sp))
        except:
            pass
    return min(candidates, key=lambda l: abs(l[0] / ref_radius - 1))[1]