r'''This function handles choosing which vertical cylinder free convection
    correlation is used. Generally this is used by a helper class, but can be
    used directly. Will automatically select the correlation to use if none is
    provided; returns None if insufficient information is provided.

    Preferred functions are 'Popiel & Churchill' for fully defined geometries,
    and 'McAdams, Weiss & Saunders' otherwise.

    Examples
    --------
    >>> Nu_vertical_cylinder(0.72, 1E7)
    30.562236756513943
    
    Parameters
    ----------
    Pr : float
        Prandtl number [-]
    Gr : float
        Grashof number with respect to cylinder height [-]
    L : float, optional
        Length of vertical cylinder, [m]
    D : float, optional
        Diameter of cylinder, [m]

    Returns
    -------
    Nu : float
        Nusselt number, [-]
    methods : list, only returned if AvailableMethods == True
        List of methods which can be used to calculate Nu with the given inputs

    Other Parameters
    ----------------
    Method : string, optional
        A string of the function name to use, as in the dictionary
        vertical_cylinder_correlations
    AvailableMethods : bool, optional
        If True, function will consider which methods which can be used to
        calculate Nu with the given inputs

def Nu_vertical_cylinder(Pr, Gr, L=None, D=None, Method=None,
                         AvailableMethods=False):
    r'''This function handles choosing which vertical cylinder free convection
    correlation is used. Generally this is used by a helper class, but can be
    used directly. Will automatically select the correlation to use if none is
    provided; returns None if insufficient information is provided.

    Preferred functions are 'Popiel & Churchill' for fully defined geometries,
    and 'McAdams, Weiss & Saunders' otherwise.

    Examples
    --------
    >>> Nu_vertical_cylinder(0.72, 1E7)
    30.562236756513943
    
    Parameters
    ----------
    Pr : float
        Prandtl number [-]
    Gr : float
        Grashof number with respect to cylinder height [-]
    L : float, optional
        Length of vertical cylinder, [m]
    D : float, optional
        Diameter of cylinder, [m]

    Returns
    -------
    Nu : float
        Nusselt number, [-]
    methods : list, only returned if AvailableMethods == True
        List of methods which can be used to calculate Nu with the given inputs

    Other Parameters
    ----------------
    Method : string, optional
        A string of the function name to use, as in the dictionary
        vertical_cylinder_correlations
    AvailableMethods : bool, optional
        If True, function will consider which methods which can be used to
        calculate Nu with the given inputs
    '''
    def list_methods():
        methods = []
        for key, values in vertical_cylinder_correlations.items():
            if values[4] or all((L, D)):
                methods.append(key)
        if 'Popiel & Churchill' in methods:
            methods.remove('Popiel & Churchill')
            methods.insert(0, 'Popiel & Churchill')
        elif 'McAdams, Weiss & Saunders' in methods:
            methods.remove('McAdams, Weiss & Saunders')
            methods.insert(0, 'McAdams, Weiss & Saunders')
        return methods

    if AvailableMethods:
        return list_methods()
    if not Method:
        Method = list_methods()[0]

    if Method in vertical_cylinder_correlations:
        if vertical_cylinder_correlations[Method][4]:
            return vertical_cylinder_correlations[Method][0](Pr=Pr, Gr=Gr)
        else:
            return vertical_cylinder_correlations[Method][0](Pr=Pr, Gr=Gr, L=L, D=D)
    else:
        raise Exception("Correlation name not recognized; see the "
                        "documentation for the available options.")