def spherical(r_1, r_2, E_1, E_2, vu_1, vu_2, P_guess=None):
    """Returns the contact parameters for two spheres in contact or for a sphere in contact with a flat surface.  In the case of a flat surface, enter None for the radius.
    
    Parameters
    ----------
    r_1 : {None, float}
        Radius of sphere 1
    r_2 : float or None
        Radius of sphere 2
    E_1 : float
        Modulus of sphere 1
    E_2 : float
        Modulus of sphere 2
    vu_1 : float
        Poisson's ratio for sphere 1
    vu_2 : float
        Poisson's ratio for sphere 2
    P_guess : float, optional
        Estimate of the applied load, by default None
    
    Returns
    -------
    float
        stiffness
    float
        stiffness exponent
    float
        contact area (Only if P_guess is given)
    float 
        max penetration parameter for use in an MSC Adams model. (Only if P_guess is given)

    Raises
    ------
    ValueError
        Raised if both radiuses are none

    """
    if r_1 is None:
        R = r_2
    elif r_2 is None:
        R = r_1
    elif r_1 is None and r_2 is None:
        raise ValueError('At least one radius must be provided!')
    else:
        R = (r_1 ** -1 + r_2 ** -1) ** -1
    E = ((1 - vu_1 ** 2) / E_1 + (1 - vu_2 ** 2) / E_2) ** -1
    k = 4 / 3 * E * R ** 0.5
    e = 3 / 2
    if P_guess is not None:
        d = (9 * P_guess ** 2 / (16 * r_1 * E ** 2)) ** (1 / 3)
        d_max = 0.3 * d
        a = (3 * P_guess * R / 4 / E) ** (1 / 3)
        return k, e, a, d_max
    else:
        return k, e
